This is the code for the statistical analysis for “Vowel Acoustics as Predictors of Speech Intelligibility in Dysarthria.”

Loading Packages

This block of code loads in the required packages for this script. In the #’s, I have provided to the code to install each package if needed.


library(rio) # install.packages('rio')
The following rio suggested packages are not installed: ‘csvy’, ‘feather’, ‘fst’, ‘hexView’, ‘readODS’, ‘rmatio’
Use 'install_formats()' to install them
library(tidyverse) # install.packages('tidyverse')
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ──────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
package ‘tidyr’ was built under R version 4.0.5package ‘readr’ was built under R version 4.0.5── Conflicts ─────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(irr) # install.packages('irr')
Loading required package: lpSolve
library(performance) # install.packages('performance')

Attaching package: ‘performance’

The following object is masked from ‘package:irr’:

    icc
library(car) # install.packages('car')
Loading required package: carData

Attaching package: ‘car’

The following object is masked from ‘package:dplyr’:

    recode

The following object is masked from ‘package:purrr’:

    some
library(ggpubr) # install.packages('ggpubr')
library(Hmisc) # install.packages('Hmisc')
Loading required package: lattice
Loading required package: survival
Loading required package: Formula

Attaching package: ‘Hmisc’

The following objects are masked from ‘package:dplyr’:

    src, summarize

The following objects are masked from ‘package:base’:

    format.pval, units
library(ggridges) # install.packages('ggridges')
library(furniture) # install.packages('furniture')
library(gt) # install.packages('gt')

Attaching package: ‘gt’

The following object is masked from ‘package:Hmisc’:

    html
library(patchwork) # install.packages('patchwork')
library(ks) # install.packages('ks')
library(emuR) # install.packages('emuR')

Attaching package: ‘emuR’

The following object is masked from ‘package:Hmisc’:

    label

The following object is masked from ‘package:car’:

    ellipse

The following object is masked from ‘package:base’:

    norm
library(mslTools) # devtools::install_github("AustinRThompson/mslTools")

Attaching package: ‘mslTools’

The following object is masked _by_ ‘.GlobalEnv’:

    cHull

Upload Datasets


# Reliability Data
Reliability <- rio::import("Prepped Data/Reliability Data.csv")

# Speaker Data
AcousticData <- rio::import("Prepped Data/AcousticMeasures.csv") %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>% # Filters out reliability data
  dplyr::select(c(Speaker,
                  Sex,
                  Etiology,
                  vowel_ED_b, # Corner Dispersion
                  VSA_b, # Traditional VSA
                  Hull_b, # VSA Hull
                  Hull_bVSD_25, # VSD 25
                  Hull_bVSD_75, # VSD 75
                  VAS, # Intelligibility (VAS)
                  transAcc) # Intelligibility (OT)
                ) %>% 
  # The following code ensure etiology, sex, and speaker are coded as factors
  dplyr::mutate(Etiology = as.factor(Etiology),
                Sex = as.factor(Sex),
                Speaker = as.factor(Speaker))

# Listener Data
Listeners <- rio::import("Prepped Data/Listener_Demographics.csv") %>%
  dplyr::select(!c(StartDate:proloficID, # removes unwanted columns
                   Q2.4_6_TEXT,
                   Q3.2_8_TEXT,
                   AudioCheck:EP3)) %>% 
  # The follow code corrects for when a listener replied "Other" instead of the Biracial or Multiracial" response
  dplyr::mutate(race = case_when(
    Q3.3_7_TEXT == "Native American/ African amercing" ~ "Biracial or Multiracial",
    TRUE ~ race
  ))

Inter-rater Reliability

Two raters (the first two authors) completed vowel segmentation for the speakers. To calculate inter-rater reliability, 20% of the speakers were segmented again by the other rater. Two-way intraclass coefficients were computed for the extracted F1 and F2 from the temporal midpoint of the vowel segments. Since only one set of ratings will be used in the data analysis, we focus on the single ICC results and interpretation. However, we also report the average ICC values to be comprehensive.

## Removing extra data frames from environment
rm(F1_Rel, F2_Rel, Reliability, Single_F1, Single_F2, Average_F1, Average_F2)
object 'F1_Rel' not foundobject 'F2_Rel' not foundobject 'Single_F1' not foundobject 'Single_F2' not foundobject 'Average_F1' not foundobject 'Average_F2' not found

Descriptive Statistics

Correlations

CorrMatrix
                 VSA_b vowel_ED_b    Hull_b Hull_bVSD_25 Hull_bVSD_75       VAS   transAcc
VSA_b        1.0000000  0.7270881 0.5542294    0.5175807   0.28240421 0.4858562 0.50853397
vowel_ED_b   0.7270881  1.0000000 0.4864838    0.3988742   0.12768894 0.4016545 0.42055730
Hull_b       0.5542294  0.4864838 1.0000000    0.8386250   0.45558161 0.2544806 0.28921519
Hull_bVSD_25 0.5175807  0.3988742 0.8386250    1.0000000   0.67628366 0.1507205 0.18077432
Hull_bVSD_75 0.2824042  0.1276889 0.4555816    0.6762837   1.00000000 0.0916510 0.08543956
VAS          0.4858562  0.4016545 0.2544806    0.1507205   0.09165100 1.0000000 0.94571449
transAcc     0.5085340  0.4205573 0.2892152    0.1807743   0.08543956 0.9457145 1.00000000

Research Q1: Modeling Intelligibility

Orthographic Transcriptions

Model 1


# Specifying Model 1
OT_Model1 <- lm(transAcc ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 
performance::check_model(OT_Model1)


## Model 1 Summary
summary(OT_Model1)

Call:
lm(formula = transAcc ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.896 -14.090   5.996  17.470  36.105 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   48.2973     9.7372   4.960  1.5e-05 ***
Hull_bVSD_25   0.6417     0.5663   1.133    0.264    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.83 on 38 degrees of freedom
Multiple R-squared:  0.03268,   Adjusted R-squared:  0.007224 
F-statistic: 1.284 on 1 and 38 DF,  p-value: 0.2643

Model 2


## Specifying Model 2
OT_Model2 <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check
performance::check_model(OT_Model2)


## Model 2 Summary
summary(OT_Model2)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-48.854 -13.962   5.567  16.758  36.257 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   47.3374    10.3316   4.582 5.09e-05 ***
Hull_bVSD_25   0.8045     0.7781   1.034    0.308    
Hull_bVSD_75  -0.7188     2.3225  -0.309    0.759    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.11 on 37 degrees of freedom
Multiple R-squared:  0.03518,   Adjusted R-squared:  -0.01698 
F-statistic: 0.6745 on 2 and 37 DF,  p-value: 0.5156
## Model 1 and Model 2 Comparison
anova(OT_Model1, OT_Model2)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 21570                           
2     37 21514  1    55.696 0.0958 0.7587

Model 3a

In this model, VSD25 was found to have a VIF value > 5. Therefore, Model 3b was created with VSD25 removed.


## Specifying Model 3
OT_Model3a <- lm(transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check
performance::check_model(OT_Model3a)

performance::check_collinearity(OT_Model3a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 2.00         1.41      0.50
       Hull_b 3.65         1.91      0.27

Moderate Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_25 5.33         2.31      0.19
## Model 3 Summary
summary(OT_Model3a)

Call:
lm(formula = transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.706 -13.157   7.018  17.957  29.990 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   31.0806    14.4916   2.145   0.0388 *
Hull_bVSD_25  -0.8439     1.2984  -0.650   0.5199  
Hull_bVSD_75   0.3159     2.3714   0.133   0.8948  
Hull_b         1.2941     0.8247   1.569   0.1253  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.65 on 36 degrees of freedom
Multiple R-squared:  0.09695,   Adjusted R-squared:  0.0217 
F-statistic: 1.288 on 3 and 36 DF,  p-value: 0.2932
## Model 2 and Model 3 Comparison
anova(OT_Model2, OT_Model3a)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: transAcc ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 21514                           
2     36 20137  1    1377.5 2.4626 0.1253

Model 3b


## Specifying Model 3

OT_Model3b <- lm(transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(OT_Model3b)

performance::check_collinearity(OT_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(OT_Model3b)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-54.371 -12.860   5.038  17.725  31.609 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   33.2337    13.9973   2.374   0.0229 *
Hull_bVSD_75  -0.6193     1.8702  -0.331   0.7424  
Hull_b         0.8605     0.4809   1.789   0.0818 .
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.47 on 37 degrees of freedom
Multiple R-squared:  0.08635,   Adjusted R-squared:  0.03697 
F-statistic: 1.749 on 2 and 37 DF,  p-value: 0.1881

Model 4


## Specifying Model 4
OT_Model4 <- lm(transAcc ~ Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

## Model 4 Assumption Check
performance::check_model(OT_Model4)

performance::check_collinearity(OT_Model4)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.68         1.30      0.60
        VSA_b 1.45         1.20      0.69
## Model 4 Summary
summary(OT_Model4)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.705 -12.573   3.108  14.504  35.215 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)   
(Intercept)   30.7726    12.7686   2.410  0.02119 * 
Hull_bVSD_75  -0.8216     1.7037  -0.482  0.63256   
Hull_b         0.1202     0.5049   0.238  0.81322   
VSA_b          5.8426     1.9859   2.942  0.00567 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.36 on 36 degrees of freedom
Multiple R-squared:  0.2634,    Adjusted R-squared:  0.2021 
F-statistic: 4.292 on 3 and 36 DF,  p-value: 0.01092
## Model 3b and Model 4 Comparison
anova(OT_Model3b, OT_Model4)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + Hull_b
Model 2: transAcc ~ Hull_bVSD_75 + Hull_b + VSA_b
  Res.Df   RSS Df Sum of Sq      F   Pr(>F)   
1     37 20373                                
2     36 16424  1    3948.9 8.6555 0.005673 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 5


## Specifying Model 5
OT_Model5 <- lm(transAcc ~ Hull_bVSD_75 + VSA_b + vowel_ED_b, data = AcousticData)

## Model 5 Assumption Check
performance::check_model(OT_Model5)

performance::check_collinearity(OT_Model5)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.10         1.05      0.91
        VSA_b 2.30         1.52      0.43
   vowel_ED_b 2.15         1.47      0.46
## Model 5 Summary
summary(OT_Model5)

Call:
lm(formula = transAcc ~ Hull_bVSD_75 + VSA_b + vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-46.501 -11.965   2.561  14.356  33.849 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   24.4273    20.1254   1.214   0.2327  
Hull_bVSD_75  -0.5814     1.5872  -0.366   0.7163  
VSA_b          5.2219     2.4990   2.090   0.0438 *
vowel_ED_b     6.0028    12.7240   0.472   0.6399  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.31 on 36 degrees of freedom
Multiple R-squared:  0.2668,    Adjusted R-squared:  0.2057 
F-statistic: 4.367 on 3 and 36 DF,  p-value: 0.0101
## Model 4 and Model 5 Comparison
anova(OT_Model4, OT_Model5)
Analysis of Variance Table

Model 1: transAcc ~ Hull_bVSD_75 + Hull_b + VSA_b
Model 2: transAcc ~ Hull_bVSD_75 + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq F Pr(>F)
1     36 16424                      
2     36 16349  0    75.229         

Final Model


## Specifying Final Model
OT_Model_final <- lm(transAcc ~ VSA_b, data = AcousticData)

## Final Model Assumption Check
performance::check_model(OT_Model_final)


## Final Model Summary
summary(OT_Model_final)

Call:
lm(formula = transAcc ~ VSA_b, data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-46.72 -12.69   2.97  14.37  35.39 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   32.508      7.857   4.138 0.000187 ***
VSA_b          5.872      1.613   3.641 0.000807 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 20.86 on 38 degrees of freedom
Multiple R-squared:  0.2586,    Adjusted R-squared:  0.2391 
F-statistic: 13.25 on 1 and 38 DF,  p-value: 0.0008068
confint(OT_Model_final)
                2.5 %    97.5 %
(Intercept) 16.602765 48.413532
VSA_b        2.606927  9.137097

VAS Models

Model 1


# Specifying Model 1
VAS_Model1 <- lm(VAS ~ Hull_bVSD_25, data = AcousticData)

## Model 1 Assumptions 
performance::check_model(VAS_Model1)


## Model 1 Summary
summary(VAS_Model1)

Call:
lm(formula = VAS ~ Hull_bVSD_25, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.625 -16.684   8.462  19.440  37.352 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.6328    10.7512   3.965 0.000313 ***
Hull_bVSD_25   0.5877     0.6253   0.940 0.353236    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.31 on 38 degrees of freedom
Multiple R-squared:  0.02272,   Adjusted R-squared:  -0.003001 
F-statistic: 0.8833 on 1 and 38 DF,  p-value: 0.3532

Model 2


## Specifying Model 2

VAS_Model2 <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

## Model 2 Assumption Check

performance::check_model(VAS_Model2)


## Model 2 Summary

summary(VAS_Model2)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-47.850 -16.576   8.382  19.448  37.237 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)   42.3384    11.4211   3.707 0.000684 ***
Hull_bVSD_25   0.6376     0.8602   0.741 0.463195    
Hull_bVSD_75  -0.2204     2.5674  -0.086 0.932036    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.66 on 37 degrees of freedom
Multiple R-squared:  0.02291,   Adjusted R-squared:  -0.0299 
F-statistic: 0.4338 on 2 and 37 DF,  p-value: 0.6513
## Model 1 and Model 2 Comparison

anova(VAS_Model1, VAS_Model2)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     38 26296                           
2     37 26291  1     5.239 0.0074  0.932

Model 3a


## Specifying Model 3a
VAS_Model3a <- lm(VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3a Assumption Check
performance::check_model(VAS_Model3a)

performance::check_collinearity(VAS_Model3a)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 2.00         1.41      0.50
       Hull_b 3.65         1.91      0.27

Moderate Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_25 5.33         2.31      0.19
## Model 3a Summary
summary(VAS_Model3a)

Call:
lm(formula = VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-56.444 -18.989   6.121  18.036  32.281 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)
(Intercept)   25.0400    16.0599   1.559    0.128
Hull_bVSD_25  -1.1164     1.4389  -0.776    0.443
Hull_bVSD_75   0.8805     2.6280   0.335    0.740
Hull_b         1.3770     0.9139   1.507    0.141

Residual standard error: 26.21 on 36 degrees of freedom
Multiple R-squared:  0.08087,   Adjusted R-squared:  0.00428 
F-statistic: 1.056 on 3 and 36 DF,  p-value: 0.3799
## Model 2 and Model 3a Comparison
anova(VAS_Model2, VAS_Model3a)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_25 + Hull_bVSD_75
Model 2: VAS ~ Hull_bVSD_25 + Hull_bVSD_75 + Hull_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     37 26291                           
2     36 24731  1    1559.6 2.2702 0.1406

Model 3b

This model removes VSD25 because of it’s high VIF value > 5.


## Specifying Model 3b

VAS_Model3b <- lm(VAS ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

## Model 3 Assumption Check

performance::check_model(VAS_Model3b)

performance::check_collinearity(VAS_Model3b)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.26         1.12      0.79
## Model 3 Summary

summary(VAS_Model3b)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + Hull_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.356 -19.394   8.036  21.298  33.412 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)   27.8884    15.5503   1.793   0.0811 .
Hull_bVSD_75  -0.3567     2.0777  -0.172   0.8646  
Hull_b         0.8034     0.5343   1.504   0.1412  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 26.07 on 37 degrees of freedom
Multiple R-squared:  0.0655,    Adjusted R-squared:  0.01499 
F-statistic: 1.297 on 2 and 37 DF,  p-value: 0.2855

Model 4


## Specifying Model 4

VAS_Model4 <- lm(VAS ~ Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

## Model 4 Assumption Check

performance::check_model(VAS_Model4)

performance::check_collinearity(VAS_Model4)
# Check for Multicollinearity

Low Correlation

         Term  VIF Increased SE Tolerance
 Hull_bVSD_75 1.26         1.12      0.79
       Hull_b 1.68         1.30      0.60
        VSA_b 1.45         1.20      0.69
## Model 4 Summary

summary(VAS_Model4)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + Hull_b + VSA_b, data = AcousticData)

Residuals:
   Min     1Q Median     3Q    Max 
-45.56 -15.17   6.40  16.64  42.62 

Coefficients:
               Estimate Std. Error t value Pr(>|t|)   
(Intercept)   2.522e+01  1.426e+01   1.768  0.08553 . 
Hull_bVSD_75 -5.762e-01  1.903e+00  -0.303  0.76382   
Hull_b        5.056e-05  5.640e-01   0.000  0.99993   
VSA_b         6.340e+00  2.218e+00   2.858  0.00705 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.86 on 36 degrees of freedom
Multiple R-squared:  0.2383,    Adjusted R-squared:  0.1748 
F-statistic: 3.754 on 3 and 36 DF,  p-value: 0.01916
## Model 3 and Model 4 Comparison

anova(VAS_Model3b, VAS_Model4)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + Hull_b
Model 2: VAS ~ Hull_bVSD_75 + Hull_b + VSA_b
  Res.Df   RSS Df Sum of Sq      F   Pr(>F)   
1     37 25145                                
2     36 20495  1    4649.8 8.1674 0.007046 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Model 5


## Specifying Model 5

VAS_Model5 <- lm(VAS ~ Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b, data = AcousticData)

## Model 5 Assumption Check

performance::check_model(VAS_Model5)


## Model 5 Summary

summary(VAS_Model5)

Call:
lm(formula = VAS ~ Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b, 
    data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.407 -13.917   7.397  16.408  41.322 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)  
(Intercept)  16.61280   23.81590   0.698    0.490  
Hull_bVSD_75 -0.40875    1.95955  -0.209    0.836  
Hull_b       -0.05465    0.58294  -0.094    0.926  
VSA_b         5.49348    2.91674   1.883    0.068 .
vowel_ED_b    6.68540   14.72389   0.454    0.653  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.13 on 35 degrees of freedom
Multiple R-squared:  0.2428,    Adjusted R-squared:  0.1562 
F-statistic: 2.805 on 4 and 35 DF,  p-value: 0.04041
## Model 4 and Model 5 Comparison

anova(VAS_Model4, VAS_Model5)
Analysis of Variance Table

Model 1: VAS ~ Hull_bVSD_75 + Hull_b + VSA_b
Model 2: VAS ~ Hull_bVSD_75 + Hull_b + VSA_b + vowel_ED_b
  Res.Df   RSS Df Sum of Sq      F Pr(>F)
1     36 20495                           
2     35 20375  1    120.02 0.2062 0.6526

Final Model


## Specifying Final Model

VAS_Model_final <- lm(VAS ~ VSA_b, data = AcousticData)

## Final Model Assumption Check

performance::check_model(VAS_Model_final)


## Final Model Summary

summary(VAS_Model_final)

Call:
lm(formula = VAS ~ VSA_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-44.956 -15.943   6.754  17.153  43.062 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)   24.703      8.761   2.820  0.00760 **
VSA_b          6.163      1.798   3.427  0.00148 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 23.26 on 38 degrees of freedom
Multiple R-squared:  0.2361,    Adjusted R-squared:  0.216 
F-statistic: 11.74 on 1 and 38 DF,  p-value: 0.001482
confint(VAS_Model_final)
               2.5 %    97.5 %
(Intercept) 6.966936 42.438084
VSA_b       2.521887  9.803467

Research Q2: Relationship between OT and VAS

Model 1


# Specify Model
OT_VAS_model <- lm(transAcc ~ VAS*Etiology + VAS*Sex, data = AcousticData)

# Assumption Check
performance::check_model(OT_VAS_model)

# Model Results
summary(OT_VAS_model)

Final Linear Model


# Specify Final Model
OT_VAS_final <- lm(transAcc ~ VAS, data = AcousticData)

# Model Results
summary(OT_VAS_final)

Call:
lm(formula = transAcc ~ VAS, data = AcousticData)

Residuals:
     Min       1Q   Median       3Q      Max 
-13.6882  -4.9316  -0.4408   4.9974  17.2110 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 13.74548    2.78681   4.932 1.64e-05 ***
VAS          0.86093    0.04799  17.938  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 7.873 on 38 degrees of freedom
Multiple R-squared:  0.8944,    Adjusted R-squared:  0.8916 
F-statistic: 321.8 on 1 and 38 DF,  p-value: < 2.2e-16
confint(OT_VAS_final)
                2.5 %     97.5 %
(Intercept) 8.1038688 19.3870846
VAS         0.7637645  0.9580856

Corner Dispersion

Looking at corner dispersion as the sole predictor.


# Specify Final Model
OT_cornDisp <- lm(transAcc ~ vowel_ED_b, data = AcousticData)
summary(OT_cornDisp)

Call:
lm(formula = transAcc ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-53.949 -10.348   4.268  14.982  25.903 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)   
(Intercept)    6.227     18.611   0.335  0.73977   
vowel_ED_b    25.564      8.946   2.857  0.00689 **
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 21.98 on 38 degrees of freedom
Multiple R-squared:  0.1769,    Adjusted R-squared:  0.1552 
F-statistic: 8.165 on 1 and 38 DF,  p-value: 0.006891
VAS_cornDisp <- lm(VAS ~ vowel_ED_b, data = AcousticData)
summary(VAS_cornDisp)

Call:
lm(formula = VAS ~ vowel_ED_b, data = AcousticData)

Residuals:
    Min      1Q  Median      3Q     Max 
-52.146 -13.413   7.142  18.719  32.964 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)  
(Intercept)   -2.859     20.636  -0.139   0.8905  
vowel_ED_b    26.819      9.920   2.704   0.0102 *
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 24.37 on 38 degrees of freedom
Multiple R-squared:  0.1613,    Adjusted R-squared:  0.1393 
F-statistic:  7.31 on 1 and 38 DF,  p-value: 0.0102

Manuscript Tables

Descriptives Table

# Prepping the descriptives data as "gtData"
gtData <- AcousticData %>%
  rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
  rbind(.,AcousticData %>%
          rbind(.,AcousticData %>%
          dplyr::mutate(Etiology = "All Etiologies")) %>%
          dplyr::mutate(Sex = "All")) %>%
  dplyr::mutate(Sex = as.factor(Sex),
                Etiology = as.factor(Etiology)) %>%
  dplyr::group_by(Sex, Etiology) %>%
  dplyr::summarize(VSA_mean = mean(VSA_b, na.rm =T),
                   VSA_sd = sd(VSA_b, na.rm = T),
                   Disp_mean = mean(vowel_ED_b, na.rm =T),
                   Disp_sd = sd(vowel_ED_b, na.rm =T),
                   Hull_mean = mean(Hull_b, na.rm =T),
                   Hull_sd = sd(Hull_b, na.rm =T),
                   VSD25_mean = mean(Hull_bVSD_25, na.rm =T),
                   VSD25_sd = sd(Hull_bVSD_25, na.rm =T),
                   VSD75_mean = mean(Hull_bVSD_75, na.rm =T),
                   VSD75_sd = sd(Hull_bVSD_75, na.rm =T),
                   VAS_mean = mean(VAS, na.rm =T),
                   VAS_sd = sd(VAS, na.rm =T),
                   OT_mean = mean(transAcc, na.rm =T),
                   OT_sd = sd(transAcc, na.rm =T)) %>%
  pivot_longer(cols = VSA_mean:OT_sd, names_to = "Measure",
               values_to = "Value") %>%
  dplyr::mutate(Value = round(Value, digits = 2),
                meanSD = ifelse(grepl("_mean",Measure),"M","sd"),
                Measure = gsub("_mean","",Measure),
                Measure = gsub("_sd","",Measure),
                Etiology = paste(Etiology,meanSD, sep = "_"),
                Sex = case_when(
                  Sex == "All" ~ "All Speakers",
                  Sex == "M" ~ "Male Speakers",
                  Sex == "F" ~ "Female Speakers"
                )) %>%
  dplyr::select(!meanSD) %>%
  pivot_wider(names_from = Etiology, values_from = "Value") %>%
  dplyr::filter(Measure != "VSD50")
`summarise()` has grouped output by 'Sex'. You can override using the `.groups` argument.
# Creating and saving the gt table
gtData %>%
  gt::gt(
    rowname_col = "Measure",
    groupname_col = "Sex",
  ) %>%
  fmt_number(
    columns = 'All Etiologies_M':PD_sd,
    decimals = 2
  ) %>%
  tab_spanner(
    label = "All Etiologies",
    columns = c('All Etiologies_M', 'All Etiologies_sd')
  ) %>%
    tab_spanner(
    label = "ALS",
    columns = c(ALS_M, ALS_sd)
  ) %>%
  tab_spanner(
    label = "PD",
    columns = c(PD_M, PD_sd)
  ) %>%
  tab_spanner(
    label = "HD",
    columns = c(HD_M, HD_sd)
  ) %>%
  tab_spanner(
    label = "Ataxic",
    columns = c(Ataxic_M, Ataxic_sd)
  ) %>%
  gt::cols_move_to_start(
    columns = c('All Etiologies_M','All Etiologies_sd')
  ) %>%
  row_group_order(
    groups = c("All Speakers", "Female Speakers", "Male Speakers")
    ) %>%
  cols_label(
     'All Etiologies_M' = "M",
     'All Etiologies_sd' = "SD",
     ALS_M = "M",
     ALS_sd = "SD",
     PD_M = "M",
     PD_sd = "SD",
     HD_M = "M",
     HD_sd = "SD",
     Ataxic_M = "M",
     Ataxic_sd = "SD"
  ) %>%
  gtsave("DescriptivesTable.html", path = "Tables")

# Removing unwanted variables
rm(gtData)

OT Model

sjPlot::tab_model(OT_Model1,
                  OT_Model2,
                  OT_Model3b,
                  OT_Model4,
                  OT_Model5,
                  OT_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/OT Models.html")

VAS Model

sjPlot::tab_model(VAS_Model1,
                  VAS_Model2,
                  VAS_Model3,
                  VAS_Model4,
                  VAS_Model5,
                  VAS_Model_final,
                  show.ci = F,
                  p.style = "stars",
                  file = "Tables/VAS Models.html")

OT vs. VAS

sjPlot::tab_model(OT_VAS_model,OT_VAS_final,
                  show.ci = F,
                  show.reflvl = TRUE,
                  p.style = "stars",
                  file = "Tables/OT and VAS Comparison.html")

Manuscript Figures

Example Measures

# Removing unwanted variables
     rm(VSAplot,
        VSDplot,
        hullPlot,
        CDplot,
        convexCoords,
        formantAlpha,
        formantColor,
        geom.text.size,
        lineAlpha,
        lineColor,
        r,
        rf,
        H_hpi,
        k,
        mat.melted,
        nconvex_25,
        nconvex_75,
        nVSD_25,
        nVSD_75,
        convex,
        vowelData,
        Formants_PRAAT,
        measuresPlot,
        plotData)
object 'VSAplot' not foundobject 'VSDplot' not foundobject 'hullPlot' not foundobject 'CDplot' not foundobject 'convexCoords' not foundobject 'formantAlpha' not foundobject 'formantColor' not foundobject 'geom.text.size' not foundobject 'lineAlpha' not foundobject 'lineColor' not foundobject 'r' not foundobject 'rf' not foundobject 'H_hpi' not foundobject 'k' not foundobject 'mat.melted' not foundobject 'nconvex_25' not foundobject 'nconvex_75' not foundobject 'nVSD_25' not foundobject 'nVSD_75' not foundobject 'convex' not foundobject 'vowelData' not foundobject 'Formants_PRAAT' not foundobject 'measuresPlot' not found

Filtering Process

    rm(filteredPlot,
       Pitch_PRAAT,
       Formants_PRAAT,
       f1,
       f2,
       f3,
       f4,
       f5,
       formantAlpha,
       myPal,
       plotData)
object 'Pitch_PRAAT' not foundobject 'Formants_PRAAT' not foundobject 'f1' not foundobject 'f2' not foundobject 'f3' not foundobject 'f4' not foundobject 'f5' not foundobject 'formantAlpha' not foundobject 'myPal' not foundobject 'plotData' not found

OT vs. VAS

plotData_Int <- AcousticData %>%
  dplyr::filter(!grepl("_rel", Speaker)) %>%
  dplyr::group_by(Speaker) %>%
  dplyr::mutate(segMin = base::min(VAS, transAcc),
                segMax = base::max(VAS, transAcc),
                ratingAvg = mean(VAS, transAcc, na.rm = T),
                Speaker = as.factor(Speaker),
                Etiology = case_when(
                  Etiology == "Ataxic" ~ "Ataxia",
                  TRUE ~ as.character(Etiology)
                ),
                Etiology = as.factor(Etiology)) %>%
  arrange(segMax)

my_pal <- c("#f26430", "#272D2D","#256eff")
# With a bit more style
plot_Int <- ggplot(plotData_Int) +
  geom_segment(aes(x = fct_inorder(Speaker),
                   xend = Speaker,
                   y = segMin,
                   yend = segMax,
                   color = Etiology)) +
  geom_point(aes(x = Speaker,
                 y = VAS,
                 color = Etiology),
             #color = my_pal[1],
             size = 3,
             shape = 19) +
  geom_point(aes(x = Speaker,
                 y = transAcc,
                 color = Etiology),
             #color = my_pal[2],
             size = 3,
             shape = 15) +
  coord_flip()+
  theme_classic() +
  theme(
    legend.position = "none",
    panel.border = element_blank(),
  ) +
  xlab("") +
  ylab("Speech Intelligibility") +
  ggtitle("Speech Intelligibility") +
  ylim(c(0,100))


myPal <- c("#1AAD77", "#1279B5", "#FFBF00", "#FD7853", "#BF3178")
myShapes <- c(16, 18, 17, 15)

OT_VASscatter <- ggplot(plotData_Int,
                  aes(x = VAS,
                      y = transAcc,
                      color = Etiology,
                      shape = Etiology,
                      linetype = Etiology)) +
  geom_point() +
  geom_smooth(method = "lm", se = F) +
  geom_abline(intercept = 0, slope = 1) +
  coord_cartesian(xlim = c(0,100), ylim = c(0,100)) +
  labs(x = "Intelligibility (VAS)", y = "Intelligibility (OT)") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myShapes) +
  theme_classic() +
  theme(aspect.ratio=1,
        legend.position="right")


ggsave(filename = "Plots/OT and VAS Scatterplot.png",
       plot = OT_VASscatter,
       height = 3.25,
       width = 4,
       units = "in",
       scale = 1)

rm(scatter1, scatter2, combinedScatter)

Model Scatterplots

modelFigureData <- AcousticData %>%
  dplyr::filter(!grepl("_rel",Speaker)) %>%
  dplyr::select(Speaker, Etiology, Sex, VSA_b, vowel_ED_b, Hull_b, Hull_bVSD_25, Hull_bVSD_75, VAS, transAcc) %>%
  dplyr::mutate(Speaker = as.factor(Speaker),
                Etiology = as.factor(Etiology),
                Sex = as.factor(Sex)) %>%
  tidyr::pivot_longer(cols = VAS:transAcc, names_to = "IntType", values_to = "Int") %>%
  dplyr::mutate(IntType = case_when(
    IntType == "transAcc" ~ "OT",
    TRUE ~ "VAS"
  ),
                IntType = as.factor(IntType))

ylabel <- "Intelligibility"
myPal <- c("#2D2D37", "#1279B5")
myPalShape <- c(19, 1)

VSA <- modelFigureData %>%
  ggplot() +
  aes(x = VSA_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  geom_smooth(method = "lm", se = F) +
  xlab(expression("VSA (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(plot.title = element_text(hjust = 0.5, face = "bold"),
        aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

disp <- modelFigureData %>%
  ggplot() +
  aes(x = vowel_ED_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  geom_smooth(method = "lm", se = F) +
  xlab("Corner Dispersion (Bark)") +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

Hull <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_b,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  geom_smooth(method = "lm", se = F) +
  xlab(expression("VSA"[Hull]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd25 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_25,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  geom_smooth(method = "lm", se = F) +
  xlab(expression("VSD"[25]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

vsd75 <- modelFigureData %>%
  ggplot() +
  aes(x = Hull_bVSD_75,
      y = Int,
      color = IntType,
      shape = IntType,
      linetype = IntType) +
  geom_point() +
  geom_smooth(method = "lm", se = T, fill = "light grey") +
  geom_smooth(method = "lm", se = F) +
  xlab(expression("VSD"[75]*" (Bark"^2*")")) +
  ylab(ylabel) +
  coord_cartesian(ylim = c(0,100)) +
  theme_classic() +
  theme(aspect.ratio=1) + theme(legend.position = "none") +
  scale_color_manual(values = myPal) +
  scale_shape_manual(values = myPalShape) +
  labs(color="Intelligibility Type",
       shape = "Intelligibility Type",
       linetype = "Intelligibility Type")

# Creating OT Scatterplot Figure

scatter <- VSA  + disp + patchwork::guide_area() + Hull + vsd25 + vsd75 +
  patchwork::plot_layout(guides = 'collect',
                         ncol = 3) & theme(legend.position = "right")
scatter 

ggsave("Plots/ModelFigure.png", scatter,
       height = 4,
       width = 6,
       units = "in",
       scale = 1.1)

Filtering at Different Levels

text_x <- 12.5
text_y <- 8.5
xlims <- c(16,5)
ylims <- c(9,1)
# Hull - 2 SD ----
Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT) %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    #dplyr::mutate(mDistOutlier = (stats::pchisq(mDist, df=1, lower.tail=FALSE)) < .001) %>%
    dplyr::filter(mDist_sd < 2)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
    Hull_b <- cHull(Formants_PRAAT$F1_b, Formants_PRAAT$F2_b)
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot_2 <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        annotate("text", x = text_x, y = text_y, label = paste("Hull =",round(Hull_b,2))) +
        scale_y_reverse() +
        scale_x_reverse() +
        xlim(xlims) +
        ylim(ylims) +
        theme_classic() + labs(title = paste("2 SD")) + xlab("F2 (Bark)") + ylab("F1 (Bark)") +
        theme(plot.title = element_text(hjust = 0.5),
              aspect.ratio = 1)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.
      hullPlot_2

      
# Hull - 2.5 SD ----
Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT) %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    #dplyr::mutate(mDistOutlier = (stats::pchisq(mDist, df=1, lower.tail=FALSE)) < .001) %>%
    dplyr::filter(mDist_sd < 2.5)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
    Hull_b <- cHull(Formants_PRAAT$F1_b, Formants_PRAAT$F2_b)
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot_2.5 <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        annotate("text", x = text_x, y = text_y, label = paste("Hull =",round(Hull_b,2))) +
        scale_y_reverse() +
        scale_x_reverse() +
        xlim(xlims) +
        ylim(ylims) +
        theme_classic() + labs(title = paste("2.5 SD")) + xlab("F2 (Bark)") + ylab("F1 (Bark)") +
        theme(plot.title = element_text(hjust = 0.5),
              aspect.ratio = 1)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.
      hullPlot_2.5

      
# Hull - 3 SD ----
Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT) %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    #dplyr::mutate(mDistOutlier = (stats::pchisq(mDist, df=1, lower.tail=FALSE)) < .001) %>%
    dplyr::filter(mDist_sd < 3)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
    Hull_b <- cHull(Formants_PRAAT$F1_b, Formants_PRAAT$F2_b)
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot_3 <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        annotate("text", x = text_x, y = text_y, label = paste("Hull =",round(Hull_b,2))) +
        scale_y_reverse() +
        scale_x_reverse() +
        xlim(xlims) +
        ylim(ylims) +
        theme_classic() + labs(title = paste("3 SD")) + xlab("F2 (Bark)") + ylab("F1 (Bark)") +
        theme(plot.title = element_text(hjust = 0.5),
              aspect.ratio = 1)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.
      hullPlot_3

      
# Hull - 1.5 SD ----
Pitch_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = ".Pitch", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = F) %>%
    dplyr::rename(Pitch = V1) %>%
    dplyr::mutate(Pitch = gsub("--undefined--",NA,Pitch),
                  Pitch = as.numeric(Pitch))

Formants_PRAAT <- list.files(path = paste("Prepped Data/Example Data", sep = ""), 
                              pattern = "_Formant", ignore.case = T) %>%
    paste("Prepped Data/Example Data/",., sep = "") %>%
    read.delim(., header = T) %>%
    dplyr::select(!c(nformants, B1.Hz., B2.Hz., B3.Hz., F4.Hz., B4.Hz., F5.Hz., B5.Hz.)) %>%
    dplyr::rename(Time_s = time.s.,
                  F1_Hz = F1.Hz.,
                  F2_Hz = F2.Hz.,
                  F3_Hz = F3.Hz.) %>%
    dplyr::mutate(F1_Hz = ifelse(F1_Hz == 0, NA, F1_Hz),
                  F2_Hz = ifelse(F2_Hz == 0, NA, F2_Hz),
                  F3_Hz = ifelse(F3_Hz == 0, NA, F3_Hz)) %>%
    dplyr::mutate(F1_Hz = as.numeric(F1_Hz),
                  F2_Hz = as.numeric(F2_Hz),
                  F3_Hz = suppressWarnings(as.numeric(F3_Hz)),
                  Time_ms = Time_s / 1000,
                  F1_kHz = F1_Hz / 1000,
                  F2_kHz = F2_Hz / 1000,
                  F3_kHz = F3_Hz / 1000,
                  F1_b = emuR::bark(F1_Hz),
                  F2_b = emuR::bark(F2_Hz),
                  F3_b = emuR::bark(F3_Hz)) %>%
    dplyr::select(!Time_s) %>%
    dplyr::relocate(Time_ms, .before = F1_Hz) %>%
    cbind(.,Pitch_PRAAT) %>%
    dplyr::filter(!is.na(Pitch)) %>%
    dplyr::mutate(F1_mad = (abs(F1_Hz - median(F1_Hz))/ mad(F1_Hz, constant = 1.4826)) > 2.5,
                  F2_mad = (abs(F2_Hz - median(F2_Hz))/ mad(F2_Hz, constant = 1.4826)) > 2.5) %>%
    dplyr::filter(F1_mad == FALSE & F2_mad == FALSE) %>%
    dplyr::mutate(mDist = mahalanobis(cbind(.$F1_Hz, .$F2_Hz),
                                      colMeans(cbind(.$F1_Hz, .$F2_Hz)),
                                      cov = cov(cbind(.$F1_Hz, .$F2_Hz))),
                  mDist_sd = abs(scale(mDist,center = T))) %>%
    #dplyr::mutate(mDistOutlier = (stats::pchisq(mDist, df=1, lower.tail=FALSE)) < .001) %>%
    dplyr::filter(mDist_sd < 1.5)
  
  c <- 2
  while(c < NROW(Formants_PRAAT)){
    Formants_PRAAT$F1_Hz[c] <- ifelse(is.na(Formants_PRAAT$F1_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F1_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F1_Hz[c])
    Formants_PRAAT$F2_Hz[c] <- ifelse(is.na(Formants_PRAAT$F2_Hz[c-1]) &&
                                        is.na(Formants_PRAAT$F2_Hz[c+1]),
                                      NA,
                                      Formants_PRAAT$F2_Hz[c])
    c <- c + 1
  }
  rm(c)
  
    Hull_b <- cHull(Formants_PRAAT$F1_b, Formants_PRAAT$F2_b)
### Plotting Hull
      convexCoords <- Formants_PRAAT %>%
        dplyr::select(F1_b, F2_b) %>%
        as.matrix() %>%
        grDevices::chull()
      convex <- Formants_PRAAT %>%
        slice(convexCoords)

      hullPlot_1.5 <- ggplot(aes(F2_b, F1_b),
                         data = Formants_PRAAT) +
        geom_point(shape = 21) +
        geom_polygon(data = convex,
                     alpha = .5,
                     color = "#1279B5",
                     fill = NA,
                     size = 1.5) +
        annotate("text", x = text_x, y = text_y, label = paste("Hull =",round(Hull_b,2))) +
        scale_y_reverse() +
        scale_x_reverse() +
        xlim(xlims) +
        ylim(ylims) +
        theme_classic() + labs(title = paste("1.5 SD")) + xlab("F2 (Bark)") + ylab("F1 (Bark)") +
        theme(plot.title = element_text(hjust = 0.5),
              aspect.ratio = 1)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the
existing scale.
Scale for 'y' is already present. Adding another scale for 'y', which will replace the
existing scale.
      hullPlot_1.5

      
# Combined ----
      ggpubr::ggarrange(hullPlot_1.5, hullPlot_2, hullPlot_2.5, hullPlot_3,
                        ncol = 4)
      ggsave(filename = "Plots/Hull at Different Filters.png",
             height = 3,
             width= 9,
             units = "in",
             scale = 1)

NA

Demographic Info

Listeners

Listeners %>%
  furniture::table1(age, gender, race, ethnicity)
Error in furniture::table1(., age, gender, race, ethnicity) : 
  object 'Listeners' not found

Speakers

LS0tCnRpdGxlOiAiVm93ZWwgQWNvdXN0aWNzIGFzIFByZWRpY3RvcnMgb2YgU3BlZWNoIEludGVsbGlnaWJpbGl0eSBpbiBEeXNhcnRocmlhIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpUaGlzIGlzIHRoZSBjb2RlIGZvciB0aGUgc3RhdGlzdGljYWwgYW5hbHlzaXMgZm9yICJWb3dlbCBBY291c3RpY3MgYXMgUHJlZGljdG9ycyBvZiBTcGVlY2ggSW50ZWxsaWdpYmlsaXR5IGluIER5c2FydGhyaWEuIgoKIyBMb2FkaW5nIFBhY2thZ2VzClRoaXMgYmxvY2sgb2YgY29kZSBsb2FkcyBpbiB0aGUgcmVxdWlyZWQgcGFja2FnZXMgZm9yIHRoaXMgc2NyaXB0LiBJbiB0aGUgIydzLCBJIGhhdmUgcHJvdmlkZWQgdG8gdGhlIGNvZGUgdG8gaW5zdGFsbCBlYWNoIHBhY2thZ2UgaWYgbmVlZGVkLgpgYGB7cn0KCmxpYnJhcnkocmlvKSAjIGluc3RhbGwucGFja2FnZXMoJ3JpbycpCmxpYnJhcnkodGlkeXZlcnNlKSAjIGluc3RhbGwucGFja2FnZXMoJ3RpZHl2ZXJzZScpCmxpYnJhcnkoaXJyKSAjIGluc3RhbGwucGFja2FnZXMoJ2lycicpCmxpYnJhcnkocGVyZm9ybWFuY2UpICMgaW5zdGFsbC5wYWNrYWdlcygncGVyZm9ybWFuY2UnKQpsaWJyYXJ5KGNhcikgIyBpbnN0YWxsLnBhY2thZ2VzKCdjYXInKQpsaWJyYXJ5KGdncHVicikgIyBpbnN0YWxsLnBhY2thZ2VzKCdnZ3B1YnInKQpsaWJyYXJ5KEhtaXNjKSAjIGluc3RhbGwucGFja2FnZXMoJ0htaXNjJykKbGlicmFyeShnZ3JpZGdlcykgIyBpbnN0YWxsLnBhY2thZ2VzKCdnZ3JpZGdlcycpCmxpYnJhcnkoZnVybml0dXJlKSAjIGluc3RhbGwucGFja2FnZXMoJ2Z1cm5pdHVyZScpCmxpYnJhcnkoZ3QpICMgaW5zdGFsbC5wYWNrYWdlcygnZ3QnKQpsaWJyYXJ5KHBhdGNod29yaykgIyBpbnN0YWxsLnBhY2thZ2VzKCdwYXRjaHdvcmsnKQpsaWJyYXJ5KGtzKSAjIGluc3RhbGwucGFja2FnZXMoJ2tzJykKbGlicmFyeShlbXVSKSAjIGluc3RhbGwucGFja2FnZXMoJ2VtdVInKQoKYGBgCgojIFVwbG9hZCBEYXRhc2V0cwpgYGB7cn0KCiMgUmVsaWFiaWxpdHkgRGF0YQpSZWxpYWJpbGl0eSA8LSByaW86OmltcG9ydCgiUHJlcHBlZCBEYXRhL1JlbGlhYmlsaXR5IERhdGEuY3N2IikKCiMgU3BlYWtlciBEYXRhCkFjb3VzdGljRGF0YSA8LSByaW86OmltcG9ydCgiUHJlcHBlZCBEYXRhL0Fjb3VzdGljTWVhc3VyZXMuY3N2IikgJT4lCiAgZHBseXI6OmZpbHRlcighZ3JlcGwoIl9yZWwiLCBTcGVha2VyKSkgJT4lICMgRmlsdGVycyBvdXQgcmVsaWFiaWxpdHkgZGF0YQogIGRwbHlyOjpzZWxlY3QoYyhTcGVha2VyLAogICAgICAgICAgICAgICAgICBTZXgsCiAgICAgICAgICAgICAgICAgIEV0aW9sb2d5LAogICAgICAgICAgICAgICAgICB2b3dlbF9FRF9iLCAjIENvcm5lciBEaXNwZXJzaW9uCiAgICAgICAgICAgICAgICAgIFZTQV9iLCAjIFRyYWRpdGlvbmFsIFZTQQogICAgICAgICAgICAgICAgICBIdWxsX2IsICMgVlNBIEh1bGwKICAgICAgICAgICAgICAgICAgSHVsbF9iVlNEXzI1LCAjIFZTRCAyNQogICAgICAgICAgICAgICAgICBIdWxsX2JWU0RfNzUsICMgVlNEIDc1CiAgICAgICAgICAgICAgICAgIFZBUywgIyBJbnRlbGxpZ2liaWxpdHkgKFZBUykKICAgICAgICAgICAgICAgICAgdHJhbnNBY2MpICMgSW50ZWxsaWdpYmlsaXR5IChPVCkKICAgICAgICAgICAgICAgICkgJT4lIAogICMgVGhlIGZvbGxvd2luZyBjb2RlIGVuc3VyZSBldGlvbG9neSwgc2V4LCBhbmQgc3BlYWtlciBhcmUgY29kZWQgYXMgZmFjdG9ycwogIGRwbHlyOjptdXRhdGUoRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpLAogICAgICAgICAgICAgICAgU2V4ID0gYXMuZmFjdG9yKFNleCksCiAgICAgICAgICAgICAgICBTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpKQoKIyBMaXN0ZW5lciBEYXRhCkxpc3RlbmVycyA8LSByaW86OmltcG9ydCgiUHJlcHBlZCBEYXRhL0xpc3RlbmVyX0RlbW9ncmFwaGljcy5jc3YiKSAlPiUKICBkcGx5cjo6c2VsZWN0KCFjKFN0YXJ0RGF0ZTpwcm9sb2ZpY0lELCAjIHJlbW92ZXMgdW53YW50ZWQgY29sdW1ucwogICAgICAgICAgICAgICAgICAgUTIuNF82X1RFWFQsCiAgICAgICAgICAgICAgICAgICBRMy4yXzhfVEVYVCwKICAgICAgICAgICAgICAgICAgIEF1ZGlvQ2hlY2s6RVAzKSkgJT4lIAogICMgVGhlIGZvbGxvdyBjb2RlIGNvcnJlY3RzIGZvciB3aGVuIGEgbGlzdGVuZXIgcmVwbGllZCAiT3RoZXIiIGluc3RlYWQgb2YgdGhlIEJpcmFjaWFsIG9yIE11bHRpcmFjaWFsIiByZXNwb25zZQogIGRwbHlyOjptdXRhdGUocmFjZSA9IGNhc2Vfd2hlbigKICAgIFEzLjNfN19URVhUID09ICJOYXRpdmUgQW1lcmljYW4vIEFmcmljYW4gYW1lcmNpbmciIH4gIkJpcmFjaWFsIG9yIE11bHRpcmFjaWFsIiwKICAgIFRSVUUgfiByYWNlCiAgKSkKYGBgCgoKIyBJbnRlci1yYXRlciBSZWxpYWJpbGl0eQpUd28gcmF0ZXJzICh0aGUgZmlyc3QgdHdvIGF1dGhvcnMpIGNvbXBsZXRlZCB2b3dlbCBzZWdtZW50YXRpb24gZm9yIHRoZSBzcGVha2Vycy4gVG8gY2FsY3VsYXRlIGludGVyLXJhdGVyIHJlbGlhYmlsaXR5LCAyMCUgb2YgdGhlIHNwZWFrZXJzIHdlcmUgc2VnbWVudGVkIGFnYWluIGJ5IHRoZSBvdGhlciByYXRlci4gVHdvLXdheSBpbnRyYWNsYXNzIGNvZWZmaWNpZW50cyB3ZXJlIGNvbXB1dGVkIGZvciB0aGUgZXh0cmFjdGVkIEYxIGFuZCBGMiBmcm9tIHRoZSB0ZW1wb3JhbCBtaWRwb2ludCBvZiB0aGUgdm93ZWwgc2VnbWVudHMuIFNpbmNlIG9ubHkgb25lIHNldCBvZiByYXRpbmdzIHdpbGwgYmUgdXNlZCBpbiB0aGUgZGF0YSBhbmFseXNpcywgd2UgZm9jdXMgb24gdGhlIHNpbmdsZSBJQ0MgcmVzdWx0cyBhbmQgaW50ZXJwcmV0YXRpb24uIEhvd2V2ZXIsIHdlIGFsc28gcmVwb3J0IHRoZSBhdmVyYWdlIElDQyB2YWx1ZXMgdG8gYmUgY29tcHJlaGVuc2l2ZS4KCmBgYHtyfQoKIyMgQ3JlYXRpbmcgbmV3IGRhdGEgZnJhbWVzIHRvIGNhbGN1bGF0ZSBJQ0MgZm9yIGV4dHJhY3RlZCBGMSBhbmQgRjIgdmFsdWVzCgpGMV9SZWwgPC0gUmVsaWFiaWxpdHkgJT4lCiAgZHBseXI6OnNlbGVjdChjKEYxLCBGMV9yZWwpKQoKRjJfUmVsIDwtIFJlbGlhYmlsaXR5ICU+JQogIGRwbHlyOjpzZWxlY3QoYyhGMiwgRjJfcmVsKSkKICAKIyMgU2luZ2xlIElDQyBmb3IgRjEKU2luZ2xlX0YxIDwtIGlycjo6aWNjKEYxX1JlbCwgbW9kZWwgPSAidHdvd2F5IiwgdHlwZSA9ICJhZ3JlZW1lbnQiLCB1bml0ID0gInNpbmdsZSIpCgojIyBBdmVyYWdlIElDQyBmb3IgRjEKQXZlcmFnZV9GMSA8LSBpcnI6OmljYyhGMV9SZWwsIG1vZGVsID0gInR3b3dheSIsIHR5cGUgPSAiYWdyZWVtZW50IiwgdW5pdCA9ICJhdmVyYWdlIikKCiMjIFNpbmdsZSBJQ0MgZm9yIEYyClNpbmdsZV9GMiA8LSBpcnI6OmljYyhGMl9SZWwsIG1vZGVsID0gInR3b3dheSIsIHR5cGUgPSAiYWdyZWVtZW50IiwgdW5pdCA9ICJzaW5nbGUiKQoKIyMgQXZlcmFnZSBJQ0MgZm9yIEYyCkF2ZXJhZ2VfRjIgPC0gaXJyOjppY2MoRjJfUmVsLCBtb2RlbCA9ICJ0d293YXkiLCB0eXBlID0gImFncmVlbWVudCIsIHVuaXQgPSAiYXZlcmFnZSIpCgojIyBJbnRlci1yYXRlciByZWxpYWJpbGl0eSByZXN1bHRzIGFuZCBpbnRlcnByZXRhdGlvbgogIHByaW50KHBhc3RlKCJTaW5nbGUgSUNDIGZvciBGMSBpcyAiLAogICAgICAgICAgICAgIHJvdW5kKFNpbmdsZV9GMSR2YWx1ZSwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIi4gIiwgCiAgICAgICAgICAgICAgIlRoZSA5NSUgQ0kgaXMgWyIsCiAgICAgICAgICAgICAgcm91bmQoU2luZ2xlX0YxJGxib3VuZCwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIiAtICIsCiAgICAgICAgICAgICAgcm91bmQoU2luZ2xlX0YxJHVib3VuZCwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIl0uIiwKICAgICAgICAgICAgICBzZXAgPSAiIikpCiAgCiAgcHJpbnQocGFzdGUoIlNpbmdsZSBJQ0MgZm9yIEYyIGlzICIsCiAgICAgICAgICAgICAgcm91bmQoU2luZ2xlX0YyJHZhbHVlLCBkaWdpdHMgPSAzKSwKICAgICAgICAgICAgICAiLiAiLCAKICAgICAgICAgICAgICAiVGhlIDk1JSBDSSBpcyBbIiwKICAgICAgICAgICAgICByb3VuZChTaW5nbGVfRjIkbGJvdW5kLCBkaWdpdHMgPSAzKSwKICAgICAgICAgICAgICAiIC0gIiwgcm91bmQoU2luZ2xlX0YyJHVib3VuZCwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIl0uIiwKICAgICAgICAgICAgICBzZXAgPSAiIikpCiAgCiAgcHJpbnQocGFzdGUoIkF2ZXJhZ2UgSUNDIGZvciBGMSBpcyAiLAogICAgICAgICAgICAgIHJvdW5kKEF2ZXJhZ2VfRjEkdmFsdWUsIGRpZ2l0cyA9IDMpLAogICAgICAgICAgICAgICIuICIsIAogICAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLAogICAgICAgICAgICAgIHJvdW5kKEF2ZXJhZ2VfRjEkbGJvdW5kLCBkaWdpdHMgPSAzKSwKICAgICAgICAgICAgICAiIC0gIiwKICAgICAgICAgICAgICByb3VuZChBdmVyYWdlX0YxJHVib3VuZCwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIl0uIiwKICAgICAgICAgICAgICBzZXAgPSAiIikpCiAgCiAgcHJpbnQocGFzdGUoIkF2ZXJhZ2UgSUNDIGZvciBGMiBpcyAiLAogICAgICAgICAgICAgIHJvdW5kKEF2ZXJhZ2VfRjIkdmFsdWUsIGRpZ2l0cyA9IDMpLAogICAgICAgICAgICAgICIuICIsIAogICAgICAgICAgICAgICJUaGUgOTUlIENJIGlzIFsiLAogICAgICAgICAgICAgIHJvdW5kKEF2ZXJhZ2VfRjIkbGJvdW5kLCBkaWdpdHMgPSAzKSwKICAgICAgICAgICAgICAiIC0gIiwKICAgICAgICAgICAgICByb3VuZChBdmVyYWdlX0YyJHVib3VuZCwgZGlnaXRzID0gMyksCiAgICAgICAgICAgICAgIl0uIiwKICAgICAgICAgICAgICBzZXAgPSAiIikpCiAgCiAgcHJpbnQoIlRodXMsIGludGVycmF0ZXIgcmVsaWFiaWxpdHkgZm9yIHRoZSBleHRyYWN0ZWQgRjEgYW5kIEYyIHZhbHVlcyBmcm9tIHRoZSB2b3dlbCBzZWdtZW50cyB3YXMgZ29vZCB0byBleGNlbGxlbnQuIikKCiMjIFJlbW92aW5nIGV4dHJhIGRhdGEgZnJhbWVzIGZyb20gZW52aXJvbm1lbnQKcm0oRjFfUmVsLCBGMl9SZWwsIFJlbGlhYmlsaXR5LCBTaW5nbGVfRjEsIFNpbmdsZV9GMiwgQXZlcmFnZV9GMSwgQXZlcmFnZV9GMikKCmBgYAoKCiMgRGVzY3JpcHRpdmUgU3RhdGlzdGljcwoKIyMgQ29ycmVsYXRpb25zCmBgYHtyfQojIENyZWF0ZXMgdGhlIGNvcnJlbGF0aW9uIG1hdHJpeApDb3JyTWF0cml4IDwtIEFjb3VzdGljRGF0YSAlPiUKICBkcGx5cjo6c2VsZWN0KFZTQV9iLCB2b3dlbF9FRF9iLCBIdWxsX2IsIEh1bGxfYlZTRF8yNSwgSHVsbF9iVlNEXzc1LCBWQVMsIHRyYW5zQWNjKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICBIbWlzYzo6cmNvcnIoKQpDb3JyTWF0cml4CgojIElkZW50aWZpZXMgc2lnbmlmaWNhbnQgY29ycmVsYXRpb25zCkNvcnJNYXRyaXhQIDwtIENvcnJNYXRyaXgkUCA8IC4wNQoKIyBQdWxscyBvdXQgdHdvIGV4YW1wbGUgY29ycmVsYXRpb25zIHRvIGJlIHNwZWNpZmllZCBpbiB0aGUgbWFudXNjcmlwdApzdGF0czo6Y29yLnRlc3QoQWNvdXN0aWNEYXRhJFZTQV9iLCBBY291c3RpY0RhdGEkdm93ZWxfRURfYiwgbWV0aG9kID0gInBlYXJzb24iKQpzdGF0czo6Y29yLnRlc3QoQWNvdXN0aWNEYXRhJEh1bGxfYiwgQWNvdXN0aWNEYXRhJEh1bGxfYlZTRF8yNSwgbWV0aG9kID0gInBlYXJzb24iKQoKIyBTYXZlcyB0aGUgY29ycmVsYXRpb24gbWF0cml4IHRvIHRoZSAiVGFibGVzIiBmb2xkZXIKd3JpdGUuY3N2KENvcnJNYXRyaXgsIGZpbGUgPSAiVGFibGVzL0NvcnJlbGF0aW9uIE1hdHJpeC5jc3YiKQoKIyBSZW1vdmVzIHVud2F0ZWQgdmFyaWFibGVzCnJtKENvcnJNYXRyaXgpCgpgYGAKCiMgUmVzZWFyY2ggUTE6IE1vZGVsaW5nIEludGVsbGlnaWJpbGl0eQoKIyMgT3J0aG9ncmFwaGljIFRyYW5zY3JpcHRpb25zCiMjIyBNb2RlbCAxCmBgYHtyfQoKIyBTcGVjaWZ5aW5nIE1vZGVsIDEKT1RfTW9kZWwxIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1LCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMSBBc3N1bXB0aW9ucyAKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsMSkKCiMjIE1vZGVsIDEgU3VtbWFyeQpzdW1tYXJ5KE9UX01vZGVsMSkKCmBgYAoKIyMjIE1vZGVsIDIKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDIKT1RfTW9kZWwyIDwtIGxtKHRyYW5zQWNjIH4gSHVsbF9iVlNEXzI1ICsgSHVsbF9iVlNEXzc1LCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMiBBc3N1bXB0aW9uIENoZWNrCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDIpCgojIyBNb2RlbCAyIFN1bW1hcnkKc3VtbWFyeShPVF9Nb2RlbDIpCgojIyBNb2RlbCAxIGFuZCBNb2RlbCAyIENvbXBhcmlzb24KYW5vdmEoT1RfTW9kZWwxLCBPVF9Nb2RlbDIpCgpgYGAKCiMjIyBNb2RlbCAzYQpJbiB0aGlzIG1vZGVsLCBWU0QyNSB3YXMgZm91bmQgdG8gaGF2ZSBhIFZJRiB2YWx1ZSA+IDUuIFRoZXJlZm9yZSwgTW9kZWwgM2Igd2FzIGNyZWF0ZWQgd2l0aCBWU0QyNSByZW1vdmVkLgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgM2EKT1RfTW9kZWwzYSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF8yNSArIEh1bGxfYlZTRF83NSArIEh1bGxfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDNhIEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsM2EpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoT1RfTW9kZWwzYSkKCiMjIE1vZGVsIDNhIFN1bW1hcnkKc3VtbWFyeShPVF9Nb2RlbDNhKQoKIyMgTW9kZWwgMiBhbmQgTW9kZWwgM2EgQ29tcGFyaXNvbgphbm92YShPVF9Nb2RlbDIsIE9UX01vZGVsM2EpCgpgYGAKCiMjIyBNb2RlbCAzYgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgM2IKT1RfTW9kZWwzYiA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDNiIEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsM2IpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoT1RfTW9kZWwzYikKCiMjIE1vZGVsIDMgU3VtbWFyeQpzdW1tYXJ5KE9UX01vZGVsM2IpCgpgYGAKCiMjIyBNb2RlbCA0CmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA0Ck9UX01vZGVsNCA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiArIFZTQV9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChPVF9Nb2RlbDQpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoT1RfTW9kZWw0KQoKIyMgTW9kZWwgNCBTdW1tYXJ5CnN1bW1hcnkoT1RfTW9kZWw0KQoKIyMgTW9kZWwgM2IgYW5kIE1vZGVsIDQgQ29tcGFyaXNvbgphbm92YShPVF9Nb2RlbDNiLCBPVF9Nb2RlbDQpCgpgYGAKCiMjIyBNb2RlbCA1CmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCA1Ck9UX01vZGVsNSA8LSBsbSh0cmFuc0FjYyB+IEh1bGxfYlZTRF83NSArIFZTQV9iICsgdm93ZWxfRURfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDUgQXNzdW1wdGlvbiBDaGVjawpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoT1RfTW9kZWw1KQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KE9UX01vZGVsNSkKCiMjIE1vZGVsIDUgU3VtbWFyeQpzdW1tYXJ5KE9UX01vZGVsNSkKCiMjIE1vZGVsIDQgYW5kIE1vZGVsIDUgQ29tcGFyaXNvbgphbm92YShPVF9Nb2RlbDQsIE9UX01vZGVsNSkKCmBgYAoKCiMjIyBGaW5hbCBNb2RlbApgYGB7cn0KCiMjIFNwZWNpZnlpbmcgRmluYWwgTW9kZWwKT1RfTW9kZWxfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX01vZGVsX2ZpbmFsKQoKIyMgRmluYWwgTW9kZWwgU3VtbWFyeQpzdW1tYXJ5KE9UX01vZGVsX2ZpbmFsKQpjb25maW50KE9UX01vZGVsX2ZpbmFsKQoKYGBgCgojIyBWQVMgTW9kZWxzCgojIyMgTW9kZWwgMQpgYGB7cn0KCiMgU3BlY2lmeWluZyBNb2RlbCAxClZBU19Nb2RlbDEgPC0gbG0oVkFTIH4gSHVsbF9iVlNEXzI1LCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgMSBBc3N1bXB0aW9ucyAKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDEpCgojIyBNb2RlbCAxIFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWwxKQoKYGBgCgojIyMgTW9kZWwgMgpgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgMgpWQVNfTW9kZWwyIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF8yNSArIEh1bGxfYlZTRF83NSwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDIgQXNzdW1wdGlvbiBDaGVjawpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsMikKCiMjIE1vZGVsIDIgU3VtbWFyeQpzdW1tYXJ5KFZBU19Nb2RlbDIpCgojIyBNb2RlbCAxIGFuZCBNb2RlbCAyIENvbXBhcmlzb24KYW5vdmEoVkFTX01vZGVsMSwgVkFTX01vZGVsMikKCmBgYAoKIyMjIE1vZGVsIDNhCmBgYHtyfQoKIyMgU3BlY2lmeWluZyBNb2RlbCAzYQpWQVNfTW9kZWwzYSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfMjUgKyBIdWxsX2JWU0RfNzUgKyBIdWxsX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCAzYSBBc3N1bXB0aW9uIENoZWNrCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWwzYSkKcGVyZm9ybWFuY2U6OmNoZWNrX2NvbGxpbmVhcml0eShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDNhIFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWwzYSkKCiMjIE1vZGVsIDIgYW5kIE1vZGVsIDNhIENvbXBhcmlzb24KYW5vdmEoVkFTX01vZGVsMiwgVkFTX01vZGVsM2EpCgpgYGAKCiMjIyBNb2RlbCAzYgpUaGlzIG1vZGVsIHJlbW92ZXMgVlNEMjUgYmVjYXVzZSBvZiBpdCdzIGhpZ2ggVklGIHZhbHVlID4gNS4KYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDNiClZBU19Nb2RlbDNiIDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIE1vZGVsIDMgQXNzdW1wdGlvbiBDaGVjawpwZXJmb3JtYW5jZTo6Y2hlY2tfbW9kZWwoVkFTX01vZGVsM2IpCnBlcmZvcm1hbmNlOjpjaGVja19jb2xsaW5lYXJpdHkoVkFTX01vZGVsM2IpCgojIyBNb2RlbCAzIFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWwzYikKCmBgYAojIyMgTW9kZWwgNApgYGB7cn0KCiMjIFNwZWNpZnlpbmcgTW9kZWwgNApWQVNfTW9kZWw0IDwtIGxtKFZBUyB+IEh1bGxfYlZTRF83NSArIEh1bGxfYiArIFZTQV9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQoKIyMgTW9kZWwgNCBBc3N1bXB0aW9uIENoZWNrCnBlcmZvcm1hbmNlOjpjaGVja19tb2RlbChWQVNfTW9kZWw0KQpwZXJmb3JtYW5jZTo6Y2hlY2tfY29sbGluZWFyaXR5KFZBU19Nb2RlbDQpCgojIyBNb2RlbCA0IFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWw0KQoKIyMgTW9kZWwgM2IgYW5kIE1vZGVsIDQgQ29tcGFyaXNvbgphbm92YShWQVNfTW9kZWwzYiwgVkFTX01vZGVsNCkKCmBgYAoKIyMjIE1vZGVsIDUKYGBge3J9CgojIyBTcGVjaWZ5aW5nIE1vZGVsIDUKVkFTX01vZGVsNSA8LSBsbShWQVMgfiBIdWxsX2JWU0RfNzUgKyBIdWxsX2IgKyBWU0FfYiArIHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIyBNb2RlbCA1IEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbDUpCgojIyBNb2RlbCA1IFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWw1KQoKIyMgTW9kZWwgNCBhbmQgTW9kZWwgNSBDb21wYXJpc29uCmFub3ZhKFZBU19Nb2RlbDQsIFZBU19Nb2RlbDUpCgpgYGAKCiMjIyBGaW5hbCBNb2RlbAoKYGBge3J9CgojIyBTcGVjaWZ5aW5nIEZpbmFsIE1vZGVsClZBU19Nb2RlbF9maW5hbCA8LSBsbShWQVMgfiBWU0FfYiwgZGF0YSA9IEFjb3VzdGljRGF0YSkKCiMjIEZpbmFsIE1vZGVsIEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKFZBU19Nb2RlbF9maW5hbCkKCiMjIEZpbmFsIE1vZGVsIFN1bW1hcnkKc3VtbWFyeShWQVNfTW9kZWxfZmluYWwpCmNvbmZpbnQoVkFTX01vZGVsX2ZpbmFsKQoKYGBgCgojIFJlc2VhcmNoIFEyOiBSZWxhdGlvbnNoaXAgYmV0d2VlbiBPVCBhbmQgVkFTCgojIyBNb2RlbCAxCmBgYHtyfQoKIyBTcGVjaWZ5IE1vZGVsCk9UX1ZBU19tb2RlbCA8LSBsbSh0cmFuc0FjYyB+IFZBUypFdGlvbG9neSArIFZBUypTZXgsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIEFzc3VtcHRpb24gQ2hlY2sKcGVyZm9ybWFuY2U6OmNoZWNrX21vZGVsKE9UX1ZBU19tb2RlbCkKCiMgTW9kZWwgUmVzdWx0cwpzdW1tYXJ5KE9UX1ZBU19tb2RlbCkKCmBgYAoKIyMgRmluYWwgTGluZWFyIE1vZGVsCgpgYGB7cn0KCiMgU3BlY2lmeSBGaW5hbCBNb2RlbApPVF9WQVNfZmluYWwgPC0gbG0odHJhbnNBY2MgfiBWQVMsIGRhdGEgPSBBY291c3RpY0RhdGEpCgojIE1vZGVsIFJlc3VsdHMKc3VtbWFyeShPVF9WQVNfZmluYWwpCmNvbmZpbnQoT1RfVkFTX2ZpbmFsKQoKYGBgCgojIENvcm5lciBEaXNwZXJzaW9uCkxvb2tpbmcgYXQgY29ybmVyIGRpc3BlcnNpb24gYXMgdGhlIHNvbGUgcHJlZGljdG9yLgoKYGBge3J9CgojIFNwZWNpZnkgRmluYWwgTW9kZWwKT1RfY29ybkRpc3AgPC0gbG0odHJhbnNBY2MgfiB2b3dlbF9FRF9iLCBkYXRhID0gQWNvdXN0aWNEYXRhKQpzdW1tYXJ5KE9UX2Nvcm5EaXNwKQoKVkFTX2Nvcm5EaXNwIDwtIGxtKFZBUyB+IHZvd2VsX0VEX2IsIGRhdGEgPSBBY291c3RpY0RhdGEpCnN1bW1hcnkoVkFTX2Nvcm5EaXNwKQoKYGBgCiMgTWFudXNjcmlwdCBUYWJsZXMKIyMgRGVzY3JpcHRpdmVzIFRhYmxlCmBgYHtyfQojIFByZXBwaW5nIHRoZSBkZXNjcmlwdGl2ZXMgZGF0YSBhcyAiZ3REYXRhIgpndERhdGEgPC0gQWNvdXN0aWNEYXRhICU+JQogIHJiaW5kKC4sQWNvdXN0aWNEYXRhICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZShFdGlvbG9neSA9ICJBbGwgRXRpb2xvZ2llcyIpKSAlPiUKICByYmluZCguLEFjb3VzdGljRGF0YSAlPiUKICAgICAgICAgIHJiaW5kKC4sQWNvdXN0aWNEYXRhICU+JQogICAgICAgICAgZHBseXI6Om11dGF0ZShFdGlvbG9neSA9ICJBbGwgRXRpb2xvZ2llcyIpKSAlPiUKICAgICAgICAgIGRwbHlyOjptdXRhdGUoU2V4ID0gIkFsbCIpKSAlPiUKICBkcGx5cjo6bXV0YXRlKFNleCA9IGFzLmZhY3RvcihTZXgpLAogICAgICAgICAgICAgICAgRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpKSAlPiUKICBkcGx5cjo6Z3JvdXBfYnkoU2V4LCBFdGlvbG9neSkgJT4lCiAgZHBseXI6OnN1bW1hcml6ZShWU0FfbWVhbiA9IG1lYW4oVlNBX2IsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTQV9zZCA9IHNkKFZTQV9iLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgICAgRGlzcF9tZWFuID0gbWVhbih2b3dlbF9FRF9iLCBuYS5ybSA9VCksCiAgICAgICAgICAgICAgICAgICBEaXNwX3NkID0gc2Qodm93ZWxfRURfYiwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgSHVsbF9tZWFuID0gbWVhbihIdWxsX2IsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIEh1bGxfc2QgPSBzZChIdWxsX2IsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTRDI1X21lYW4gPSBtZWFuKEh1bGxfYlZTRF8yNSwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVlNEMjVfc2QgPSBzZChIdWxsX2JWU0RfMjUsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZTRDc1X21lYW4gPSBtZWFuKEh1bGxfYlZTRF83NSwgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgVlNENzVfc2QgPSBzZChIdWxsX2JWU0RfNzUsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZBU19tZWFuID0gbWVhbihWQVMsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIFZBU19zZCA9IHNkKFZBUywgbmEucm0gPVQpLAogICAgICAgICAgICAgICAgICAgT1RfbWVhbiA9IG1lYW4odHJhbnNBY2MsIG5hLnJtID1UKSwKICAgICAgICAgICAgICAgICAgIE9UX3NkID0gc2QodHJhbnNBY2MsIG5hLnJtID1UKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBWU0FfbWVhbjpPVF9zZCwgbmFtZXNfdG8gPSAiTWVhc3VyZSIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJWYWx1ZSIpICU+JQogIGRwbHlyOjptdXRhdGUoVmFsdWUgPSByb3VuZChWYWx1ZSwgZGlnaXRzID0gMiksCiAgICAgICAgICAgICAgICBtZWFuU0QgPSBpZmVsc2UoZ3JlcGwoIl9tZWFuIixNZWFzdXJlKSwiTSIsInNkIiksCiAgICAgICAgICAgICAgICBNZWFzdXJlID0gZ3N1YigiX21lYW4iLCIiLE1lYXN1cmUpLAogICAgICAgICAgICAgICAgTWVhc3VyZSA9IGdzdWIoIl9zZCIsIiIsTWVhc3VyZSksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IHBhc3RlKEV0aW9sb2d5LG1lYW5TRCwgc2VwID0gIl8iKSwKICAgICAgICAgICAgICAgIFNleCA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgU2V4ID09ICJBbGwiIH4gIkFsbCBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiTSIgfiAiTWFsZSBTcGVha2VycyIsCiAgICAgICAgICAgICAgICAgIFNleCA9PSAiRiIgfiAiRmVtYWxlIFNwZWFrZXJzIgogICAgICAgICAgICAgICAgKSkgJT4lCiAgZHBseXI6OnNlbGVjdCghbWVhblNEKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gRXRpb2xvZ3ksIHZhbHVlc19mcm9tID0gIlZhbHVlIikgJT4lCiAgZHBseXI6OmZpbHRlcihNZWFzdXJlICE9ICJWU0Q1MCIpCgojIENyZWF0aW5nIGFuZCBzYXZpbmcgdGhlIGd0IHRhYmxlCmd0RGF0YSAlPiUKICBndDo6Z3QoCiAgICByb3duYW1lX2NvbCA9ICJNZWFzdXJlIiwKICAgIGdyb3VwbmFtZV9jb2wgPSAiU2V4IiwKICApICU+JQogIGZtdF9udW1iZXIoCiAgICBjb2x1bW5zID0gJ0FsbCBFdGlvbG9naWVzX00nOlBEX3NkLAogICAgZGVjaW1hbHMgPSAyCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIkFsbCBFdGlvbG9naWVzIiwKICAgIGNvbHVtbnMgPSBjKCdBbGwgRXRpb2xvZ2llc19NJywgJ0FsbCBFdGlvbG9naWVzX3NkJykKICApICU+JQogICAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJBTFMiLAogICAgY29sdW1ucyA9IGMoQUxTX00sIEFMU19zZCkKICApICU+JQogIHRhYl9zcGFubmVyKAogICAgbGFiZWwgPSAiUEQiLAogICAgY29sdW1ucyA9IGMoUERfTSwgUERfc2QpCiAgKSAlPiUKICB0YWJfc3Bhbm5lcigKICAgIGxhYmVsID0gIkhEIiwKICAgIGNvbHVtbnMgPSBjKEhEX00sIEhEX3NkKQogICkgJT4lCiAgdGFiX3NwYW5uZXIoCiAgICBsYWJlbCA9ICJBdGF4aWMiLAogICAgY29sdW1ucyA9IGMoQXRheGljX00sIEF0YXhpY19zZCkKICApICU+JQogIGd0Ojpjb2xzX21vdmVfdG9fc3RhcnQoCiAgICBjb2x1bW5zID0gYygnQWxsIEV0aW9sb2dpZXNfTScsJ0FsbCBFdGlvbG9naWVzX3NkJykKICApICU+JQogIHJvd19ncm91cF9vcmRlcigKICAgIGdyb3VwcyA9IGMoIkFsbCBTcGVha2VycyIsICJGZW1hbGUgU3BlYWtlcnMiLCAiTWFsZSBTcGVha2VycyIpCiAgICApICU+JQogIGNvbHNfbGFiZWwoCiAgICAgJ0FsbCBFdGlvbG9naWVzX00nID0gIk0iLAogICAgICdBbGwgRXRpb2xvZ2llc19zZCcgPSAiU0QiLAogICAgIEFMU19NID0gIk0iLAogICAgIEFMU19zZCA9ICJTRCIsCiAgICAgUERfTSA9ICJNIiwKICAgICBQRF9zZCA9ICJTRCIsCiAgICAgSERfTSA9ICJNIiwKICAgICBIRF9zZCA9ICJTRCIsCiAgICAgQXRheGljX00gPSAiTSIsCiAgICAgQXRheGljX3NkID0gIlNEIgogICkgJT4lCiAgZ3RzYXZlKCJEZXNjcmlwdGl2ZXNUYWJsZS5odG1sIiwgcGF0aCA9ICJUYWJsZXMiKQoKIyBSZW1vdmluZyB1bndhbnRlZCB2YXJpYWJsZXMKcm0oZ3REYXRhKQpgYGAKCiMjIE9UIE1vZGVsCmBgYHtyfQpzalBsb3Q6OnRhYl9tb2RlbChPVF9Nb2RlbDEsCiAgICAgICAgICAgICAgICAgIE9UX01vZGVsMiwKICAgICAgICAgICAgICAgICAgT1RfTW9kZWwzYiwKICAgICAgICAgICAgICAgICAgT1RfTW9kZWw0LAogICAgICAgICAgICAgICAgICBPVF9Nb2RlbDUsCiAgICAgICAgICAgICAgICAgIE9UX01vZGVsX2ZpbmFsLAogICAgICAgICAgICAgICAgICBzaG93LmNpID0gRiwKICAgICAgICAgICAgICAgICAgcC5zdHlsZSA9ICJzdGFycyIsCiAgICAgICAgICAgICAgICAgIGZpbGUgPSAiVGFibGVzL09UIE1vZGVscy5odG1sIikKYGBgCgojIyBWQVMgTW9kZWwKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKFZBU19Nb2RlbDEsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDIsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDMsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDQsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbDUsCiAgICAgICAgICAgICAgICAgIFZBU19Nb2RlbF9maW5hbCwKICAgICAgICAgICAgICAgICAgc2hvdy5jaSA9IEYsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9WQVMgTW9kZWxzLmh0bWwiKQpgYGAKCiMjIE9UIHZzLiBWQVMKYGBge3J9CnNqUGxvdDo6dGFiX21vZGVsKE9UX1ZBU19tb2RlbCxPVF9WQVNfZmluYWwsCiAgICAgICAgICAgICAgICAgIHNob3cuY2kgPSBGLAogICAgICAgICAgICAgICAgICBzaG93LnJlZmx2bCA9IFRSVUUsCiAgICAgICAgICAgICAgICAgIHAuc3R5bGUgPSAic3RhcnMiLAogICAgICAgICAgICAgICAgICBmaWxlID0gIlRhYmxlcy9PVCBhbmQgVkFTIENvbXBhcmlzb24uaHRtbCIpCmBgYAoKIyBNYW51c2NyaXB0IEZpZ3VyZXMKIyMgRXhhbXBsZSBNZWFzdXJlcwpgYGB7cn0KZm9ybWFudENvbG9yIDwtICJncmV5Igpmb3JtYW50QWxwaGEgPC0gLjk1CmxpbmVDb2xvciA8LSAid2hpdGUiCmxpbmVBbHBoYSA8LSAuOAoKIyMgTG9hZGluZyBleGFtcGxlIGRhdGEgLS0tLQp2b3dlbERhdGEgPC0gcmlvOjppbXBvcnQoIlByZXBwZWQgRGF0YS9Wb3dlbCBEYXRhLmNzdiIpICU+JQogIGRwbHlyOjpmaWx0ZXIoU3BlYWtlciA9PSAiQUY4IikKCiAgUGl0Y2hfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCiAgCiAgRm9ybWFudHNfUFJBQVQgPC0gbGlzdC5maWxlcyhwYXRoID0gcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJfRm9ybWFudCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gVCkgJT4lCiAgICBkcGx5cjo6c2VsZWN0KCFjKG5mb3JtYW50cywgQjEuSHouLCBCMi5Iei4sIEIzLkh6LiwgRjQuSHouLCBCNC5Iei4sIEY1Lkh6LiwgQjUuSHouKSkgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFRpbWVfcyA9IHRpbWUucy4sCiAgICAgICAgICAgICAgICAgIEYxX0h6ID0gRjEuSHouLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IEYyLkh6LiwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBGMy5Iei4pICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9IeiA9IGlmZWxzZShGMV9IeiA9PSAwLCBOQSwgRjFfSHopLAogICAgICAgICAgICAgICAgICBGMl9IeiA9IGlmZWxzZShGMl9IeiA9PSAwLCBOQSwgRjJfSHopLAogICAgICAgICAgICAgICAgICBGM19IeiA9IGlmZWxzZShGM19IeiA9PSAwLCBOQSwgRjNfSHopKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBhcy5udW1lcmljKEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBhcy5udW1lcmljKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBzdXBwcmVzc1dhcm5pbmdzKGFzLm51bWVyaWMoRjNfSHopKSwKICAgICAgICAgICAgICAgICAgVGltZV9tcyA9IFRpbWVfcyAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYxX2tIeiA9IEYxX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjJfa0h6ID0gRjJfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGM19rSHogPSBGM19IeiAvIDEwMDApICU+JQogICAgZHBseXI6OnNlbGVjdCghVGltZV9zKSAlPiUKICAgIGRwbHlyOjpyZWxvY2F0ZShUaW1lX21zLCAuYmVmb3JlID0gRjFfSHopICU+JQogICAgY2JpbmQoLixQaXRjaF9QUkFBVCkKICAKICBjIDwtIDIKICB3aGlsZShjIDwgTlJPVyhGb3JtYW50c19QUkFBVCkpewogICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSkKICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10pCiAgICBjIDwtIGMgKyAxCiAgfQogIHJtKGMpCiAgCiAgRm9ybWFudHNfUFJBQVQgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgRjJfbWFkID0gKGFicyhGMl9IeiAtIG1lZGlhbihGMl9IeikpLyBtYWQoRjJfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUpICU+JQogICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgZHBseXI6Om11dGF0ZShtRGlzdCA9IG1haGFsYW5vYmlzKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbE1lYW5zKGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3YgPSBjb3YoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpKSwKICAgICAgICAgICAgICAgICAgbURpc3Rfc2QgPSBhYnMoc2NhbGUobURpc3QsY2VudGVyID0gVCkpKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIobURpc3Rfc2QgPCAyKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIWMoRjFfbWFkLCBGMl9tYWQsIG1EaXN0LCBtRGlzdF9zZCkpICU+JQogICAgZHBseXI6Om11dGF0ZShGMV96ID0gc2NhbGUoRjFfSHosIGNlbnRlciA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBGMl96ID0gc2NhbGUoRjJfSHosIGNlbnRlciA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBGM196ID0gc2NhbGUoRjNfSHosIGNlbnRlciA9IFRSVUUpLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKQogIAogIHJtKFBpdGNoX1BSQUFUKQogIAogIAojIyBDb3JuZXIgRGlzcGVyc2lvbiAtLS0tCiAgd2VkZ2UgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gInYiKQogICAgCiAgY29ybmVyX2RpcyA8LSB2b3dlbERhdGEgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsICE9ICJ2IikgJT4lCiAgICBkcGx5cjo6Z3JvdXBfYnkoVm93ZWwpICU+JQogICAgZHBseXI6OnN1bW1hcml6ZShtZWFuX0YxID0gbWVhbihGMV90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YyID0gbWVhbihGMl90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX3ogPSBtZWFuKEYxX3pfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl96ID0gbWVhbihGMl96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjFfYiA9IG1lYW4oRjFfYl90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YyX2IgPSBtZWFuKEYyX2JfdGVtcE1pZCkpICU+JQogICAgZHBseXI6Om11dGF0ZShWb3dlbF9FRCA9IHNxcnQoKG1lYW5fRjEtd2VkZ2UkbWVhbl9GMSleMiArIChtZWFuX0YyLXdlZGdlJG1lYW5fRjIpXjIpLAogICAgICAgICAgICAgICAgICBWb3dlbF9FRF96ID0gc3FydCgobWVhbl9GMV96LXdlZGdlJG1lYW5fRjFfeileMiArIChtZWFuX0YyX3otd2VkZ2UkbWVhbl9GMl96KV4yKSwKICAgICAgICAgICAgICAgICAgVm93ZWxfRURfYiA9IHNxcnQoKG1lYW5fRjFfYi13ZWRnZSRtZWFuX0YxX2IpXjIgKyAobWVhbl9GMl9iLXdlZGdlJG1lYW5fRjJfYileMikpCgogICAgCiMgUGxvdCBDb3JuZXIgRGlzcGVyc2lvbgogICAgICAjIENoYW5naW5nIHRvIElQQSBzeW1ib2xzCiAgICAgIGNvcm5lcl9kaXMgPC0gY29ybmVyX2RpcyAlPiUKICAgICAgICBkcGx5cjo6bXV0YXRlKFZvd2VsID0gZHBseXI6OmNhc2Vfd2hlbigKICAgICAgICAgIFZvd2VsID09ICJhZSIgfiAiw6YiLAogICAgICAgICAgVFJVRSB+IFZvd2VsCiAgICAgICAgKSkKICAgICAgCiAgICAgIHdlZGdlIDwtIHdlZGdlICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoVm93ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAidiIgfiAiyowiLAogICAgICAgICAgVFJVRSB+IFZvd2VsCiAgICAgICAgKSkKICAgICAgCiAgICAgIENEcGxvdCA8LSBnZ3Bsb3QoYWVzKHg9RjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgeT1GMV9iKSwKICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICAgaW5oZXJpdC5hZXMgPSBGQUxTRSkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLAogICAgICAgICAgICAgICAgIGFscGhhID0gZm9ybWFudEFscGhhLAogICAgICAgICAgICAgICAgIGNvbG9yID0gZm9ybWFudENvbG9yKSArIAogICAgICBnZW9tX2xpbmUoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgeSA9IG1lYW5fRjFfYiksCiAgICAgICAgICAgICAgICBkYXRhID0gY29ybmVyX2RpcyAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OnNlbGVjdChWb3dlbDptZWFuX0YyX2IpICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKFZvd2VsID09ICJpIikgJT4lCiAgICAgICAgICAgICAgICAgIHJiaW5kKC4sd2VkZ2UpLAogICAgICAgICAgICAgICAgY29sb3IgPSBsaW5lQ29sb3IsCiAgICAgICAgICAgICAgICBzaXplID0gMS41LAogICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEpICsKICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IpLAogICAgICAgICAgICAgICAgZGF0YSA9IGNvcm5lcl9kaXMgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoVm93ZWw6bWVhbl9GMl9iKSAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihWb3dlbCA9PSAiYSIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fbGluZShhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoVm93ZWwgPT0gIsOmIikgJT4lCiAgICAgICAgICAgICAgICAgIHJiaW5kKC4sd2VkZ2UpLAogICAgICAgICAgICAgICAgY29sb3IgPSBsaW5lQ29sb3IsCiAgICAgICAgICAgICAgICBzaXplID0gMS41LAogICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEpICsKICAgICAgZ2VvbV9saW5lKGFlcyh4ID0gbWVhbl9GMl9iLAogICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IpLAogICAgICAgICAgICAgICAgZGF0YSA9IGNvcm5lcl9kaXMgJT4lCiAgICAgICAgICAgICAgICAgIGRwbHlyOjpzZWxlY3QoVm93ZWw6bWVhbl9GMl9iKSAlPiUKICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihWb3dlbCA9PSAidSIpICU+JQogICAgICAgICAgICAgICAgICByYmluZCguLHdlZGdlKSwKICAgICAgICAgICAgICAgIGNvbG9yID0gbGluZUNvbG9yLAogICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSwKICAgICAgICAgICAgICAgIGFscGhhID0gbGluZUFscGhhKSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gVm93ZWwpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBjb3JuZXJfZGlzICU+JQogICAgICAgICAgICAgICAgICBkcGx5cjo6c2VsZWN0KFZvd2VsOm1lYW5fRjJfYikgJT4lCiAgICAgICAgICAgICAgICAgIHJiaW5kKC4sd2VkZ2UpLAogICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiQ29ybmVyIERpc3BlcnNpb24iKSkgKyB4bGFiKCJGMiAoQmFyaykiKSArIHlsYWIoIkYxIChCYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhIiA9ICIjMUFBRDc3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDpiIgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaSIgPSAiI0ZGQkYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidSIgPSAiI0ZENzg1MyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiyowiID0gIiNCRjMxNzgiKSkKICAgIAogICAgICBybShjb3JuZXJfZGlzLCB3ZWRnZSkKICAgICAgCiMjIFZvd2VsIFNwYWNlIEFyZWEgLS0tLQogIFZTQV9jb29yZHMgPC0gdm93ZWxEYXRhICU+JQogICAgZHBseXI6OmZpbHRlcihWb3dlbCAhPSAidiIpICU+JQogICAgZHBseXI6Omdyb3VwX2J5KFZvd2VsKSAlPiUKICAgIGRwbHlyOjpzdW1tYXJpemUobWVhbl9GMSA9IG1lYW4oRjFfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMiA9IG1lYW4oRjJfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMV96ID0gbWVhbihGMV96X3RlbXBNaWQpLAogICAgICAgICAgICAgIG1lYW5fRjJfeiA9IG1lYW4oRjJfel90ZW1wTWlkKSwKICAgICAgICAgICAgICBtZWFuX0YxX2IgPSBtZWFuKEYxX2JfdGVtcE1pZCksCiAgICAgICAgICAgICAgbWVhbl9GMl9iID0gbWVhbihGMl9iX3RlbXBNaWQpKSAKICAKIyMjIFBsb3R0aW5nIFZTQQogICAgVlNBX2Nvb3JkcyA8LSBWU0FfY29vcmRzICU+JQogICAgICAgIGRwbHlyOjptdXRhdGUoVm93ZWwgPSBjYXNlX3doZW4oCiAgICAgICAgICBWb3dlbCA9PSAiYWUiIH4gIsOmIiwKICAgICAgICAgIFRSVUUgfiBWb3dlbAogICAgICAgICkpCiAgICAKICAgIFZTQXBsb3QgPC0gZ2dwbG90KGFlcyh4ID0gRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQsCiAgICAgICAgICAgICAgICAgICAgICBpbmhlcml0LmFlcyA9IEZBTFNFKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsgCiAgICAgIGdlb21fcG9seWdvbihhZXMoeCA9IG1lYW5fRjJfYiwKICAgICAgICAgICAgICAgICAgICAgICB5ID0gbWVhbl9GMV9iKSwKICAgICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgICAgYWxwaGEgPSBsaW5lQWxwaGEsCiAgICAgICAgICAgICAgICAgICBjb2xvciA9IGxpbmVDb2xvciwKICAgICAgICAgICAgICAgICAgIGZpbGw9TkEsCiAgICAgICAgICAgICAgICAgICBzaXplID0gMS41KSArCiAgICAgIGdlb21fcG9pbnQoYWVzKHggPSBtZWFuX0YyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBtZWFuX0YxX2IsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gVm93ZWwpLAogICAgICAgICAgICAgICAgIGRhdGEgPSBWU0FfY29vcmRzLAogICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UsCiAgICAgICAgICAgICAgICAgc2l6ZSA9IDUpICsKICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArCiAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSAiVlNBIikgKyB4bGFiKCJGMiAoQmFyaykiKSArIHlsYWIoIkYxIChCYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgICAgICAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJhIiA9ICIjMUFBRDc3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICLDpiIgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiaSIgPSAiI0ZGQkYwMCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAidSIgPSAiI0ZENzg1MyIpKQogIAogIHJtKFZTQV9jb29yZHMpCiAgCiMjIEh1bGwgLS0tLQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90IDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsCiAgICAgICAgICAgICAgICAgYWxwaGEgPSBmb3JtYW50QWxwaGEsCiAgICAgICAgICAgICAgICAgY29sb3IgPSBmb3JtYW50Q29sb3IpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IGV4cHJlc3Npb24oIlZTQSJbSHVsbF0pKSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHhsYWIoIkYyIChCYXJrKSIpICsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeWxhYigiRjEgKEJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSkKICAgIAogIAojIyBWb3dlbCBTcGFjZSBEZW5zaXR5IC0tLS0KCiMgc2VsZWN0aW5nIHRoZSBiYW5kd2lkdGgKSF9ocGkgPC0ga3M6OkhwaSh4ID0gRm9ybWFudHNfUFJBQVRbLGMoIkYyX2IiLCJGMV9iIildLCBwaWxvdCA9ICJzYW1zZSIsIHByZSA9ICJzY2FsZSIsIGJpbm5lZCA9IFQpCgojIGNvbXB1dGUgMmQga2RlCmsgPC0ga2RlKHggPSBGb3JtYW50c19QUkFBVFssYygiRjJfYiIsIkYxX2IiKV0sCiAgICAgICAgIEggPSBIX2hwaSwKICAgICAgICAgYmlubmVkID0gVCwKICAgICAgICAgZ3JpZHNpemUgPSAyNTApCgojZGVuc2l0eSA8LSBrW1siZXN0aW1hdGUiXV0KCiMgQmVmb3JlIHdlIGNhbiBwbG90IHRoZSBkZW5zaXR5IGVzdGltYXRlIHdlIG5lZWQgdG8gbWVsdCBpdCBpbnRvIGxvbmcgZm9ybWF0Cm1hdC5tZWx0ZWQgPC0gZGF0YS50YWJsZTo6bWVsdChrJGVzdGltYXRlKQpuYW1lcyhtYXQubWVsdGVkKSA8LSBjKCJ4IiwgInkiLCAiZGVuc2l0eSIpCgojIFdlIG5lZWQgdG8gYWRkIHR3byBtb3JlIGNvbHVtcyB0byBwcmVzZXJ2ZSB0aGUgYXhlcyB1bml0cwptYXQubWVsdGVkJEYyLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzFdXSwgdGltZXMgPSBucm93KGskZXN0aW1hdGUpKQptYXQubWVsdGVkJEYxLmIgPC0gcmVwKGskZXZhbC5wb2ludHNbWzJdXSwgZWFjaCA9IG5yb3coayRlc3RpbWF0ZSkpCm1hdC5tZWx0ZWQkZGVuc2l0eSA8LSBzY2FsZXM6OnJlc2NhbGUobWF0Lm1lbHRlZCRkZW5zaXR5LCB0byA9IGMoMCwgMSkpCgojIFZTRCAtIDI1Cm5WU0RfMjUgPC0gbWF0Lm1lbHRlZCAlPiUKICBkcGx5cjo6ZmlsdGVyKGRlbnNpdHkgPiAuMjUpICU+JQogIGRwbHlyOjpzZWxlY3QoRjIuYixGMS5iLCBkZW5zaXR5KSAlPiUKICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KQoKY29udmV4Q29vcmRzIDwtIG5WU0RfMjUgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLCBGMS5iKSAlPiUKICBhcy5tYXRyaXgoKSAlPiUKICAjZ3JEZXZpY2VzOjp4eS5jb29yZHMoKSAlPiUKICBnckRldmljZXM6OmNodWxsKCkKbmNvbnZleF8yNSA8LSBuVlNEXzI1ICU+JQogIHNsaWNlKGNvbnZleENvb3JkcykKCiMgVlNEIC0gNzUKblZTRF83NSA8LSBtYXQubWVsdGVkICU+JQogIGRwbHlyOjpmaWx0ZXIoZGVuc2l0eSA+IC43NSkgJT4lCiAgZHBseXI6OnNlbGVjdChGMi5iLEYxLmIsIGRlbnNpdHkpICU+JQogIGRwbHlyOjpyZW5hbWUoRGVuc2l0eSA9IGRlbnNpdHkpCgpjb252ZXhDb29yZHMgPC0gblZTRF83NSAlPiUKICBkcGx5cjo6c2VsZWN0KEYyLmIsIEYxLmIpICU+JQogIGFzLm1hdHJpeCgpICU+JQogIGdyRGV2aWNlczo6Y2h1bGwoKQpuY29udmV4Xzc1IDwtIG5WU0RfNzUgJT4lCiAgc2xpY2UoY29udmV4Q29vcmRzKQoKIyBQbG90dGluZyBaIE5vcm1hbGl6ZWQgVlNEIAogICAgcmYgPC0gY29sb3JSYW1wUGFsZXR0ZShyZXYoUkNvbG9yQnJld2VyOjpicmV3ZXIucGFsKDExLCAiU3BlY3RyYWwiKSkpCiAgICByIDwtIHJmKDMyKQogICAgCiAgICBwbG90RGF0YSA8LSBtYXQubWVsdGVkICU+JQogICAgICAgICAgICAgICAgICAgICAgICBkcGx5cjo6cmVuYW1lKERlbnNpdHkgPSBkZW5zaXR5KSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAgZHBseXI6Om11dGF0ZShWU0RsYWJlbCA9IGRwbHlyOjpjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICAgICAgRGVuc2l0eSA8IC4yNSB+ICJub25lIiwKICAgICAgICAgICAgICAgICAgICAgICAgICBEZW5zaXR5ID4gLjI1ICYmIERlbnNpdHkgPCAuNzUgfiAiVlNEMjUiLAogICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiVlNENzUiCiAgICAgICAgICAgICAgICAgICAgICAgICkpCmdlb20udGV4dC5zaXplIDwtIDIKICAgIFZTRHBsb3QgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICAgICAgIGFlcyh4ID0gRjIuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICB5ID0gRjEuYiwKICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxsID0gRGVuc2l0eSkpICsgCiAgICAgIGdlb21fdGlsZSgpICsgCiAgICAgIHNjYWxlX2ZpbGxfdmlyaWRpc19jKCkgKwogICAgICBzY2FsZV94X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwgCiAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSByb3VuZChzZXEobWluKG1hdC5tZWx0ZWQkRjIuYiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heChtYXQubWVsdGVkJEYyLmIpLCBieSA9IDIpKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UoZXhwYW5kID0gYygwLCAwKSwKICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHJvdW5kKHNlcShtaW4obWF0Lm1lbHRlZCRGMS5iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXgobWF0Lm1lbHRlZCRGMS5iKSwgYnkgPSAyKSkpICsgCiAgICAgIHlsYWIoIkYxIChCYXJrKSIpICsgeGxhYigiRjIgKEJhcmspIikgKwogICAgICBsYWJzKHRpdGxlID0gIlZTRCIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpICsKICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBuY29udmV4XzI1LCBhbHBoYSA9IGxpbmVBbHBoYSwgY29sb3IgPSBsaW5lQ29sb3IsIHNpemUgPSAxLjUsIGZpbGwgPSBOQSwgbGluZXR5cGUgPSAyKSArCiAgICAgIGdlb21fcG9seWdvbihkYXRhID0gbmNvbnZleF83NSwgYWxwaGEgPSBsaW5lQWxwaGEsIGNvbG9yID0gbGluZUNvbG9yLCBzaXplID0gMS41LCBmaWxsID0gTkEsIGxpbmV0eXBlID0gMSkgKwogICAgIyBWU0QgMjUgTGFiZWwKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJjdXJ2ZSIsCiAgICAgICAgICAgICAgIHggPSA2LjksIHkgPSAxLjcrLjUsCiAgICAgICAgICAgICAgIHhlbmQgPSA4LjUsIHllbmQgPSAzLjUsCiAgICAgICAgICAgICAgIGN1cnZhdHVyZSA9IC0uMywKICAgICAgICAgICAgICAgYXJyb3cgPSBhcnJvdyhsZW5ndGggPSB1bml0KDIsICJtbSIpKSwKICAgICAgICAgICAgICAgY29sb3IgPSAid2hpdGUiKSArCiAgICAgIGFubm90YXRlKGdlb20gPSAidGV4dCIsCiAgICAgICAgICAgICAgIHggPSA3LjUsIHkgPSAxLjcsCiAgICAgICAgICAgICAgIGxhYmVsID0gZGVwYXJzZShicXVvdGUoVlNEWzI1XSkpLAogICAgICAgICAgICAgICBoanVzdCA9ICJjZW50ZXIiLAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsCiAgICAgICAgICAgICAgIHBhcnNlPVRSVUUpICsKICAgICMgVlNEIDc1IExhYmVsCiAgICAgIGFubm90YXRlKGdlb20gPSAiY3VydmUiLAogICAgICAgICAgICAgICB4ID0gNy41LCB5ID0gNy41LS41LAogICAgICAgICAgICAgICB4ZW5kID0gMTEuMzUsIHllbmQgPSA1LjUsCiAgICAgICAgICAgICAgIGN1cnZhdHVyZSA9IC4zLAogICAgICAgICAgICAgICBhcnJvdyA9IGFycm93KGxlbmd0aCA9IHVuaXQoMiwgIm1tIikpLAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIpICsKICAgICAgYW5ub3RhdGUoZ2VvbSA9ICJ0ZXh0IiwKICAgICAgICAgICAgICAgeCA9IDcsIHkgPSA3LjUsCiAgICAgICAgICAgICAgIGxhYmVsID0gZGVwYXJzZShicXVvdGUoVlNEWzc1XSkpLAogICAgICAgICAgICAgICBoanVzdCA9ICJjZW50ZXIiLAogICAgICAgICAgICAgICBjb2xvciA9ICJ3aGl0ZSIsCiAgICAgICAgICAgICAgIHBhcnNlID0gVFJVRSkKCiMjIENvbWJpbmluZyB0aGUgUGxvdHMgLS0tLQogICAgIHJvdzEgPC0gVlNBcGxvdCArIENEcGxvdCArCiAgICAgICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMikgJiB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAncmlnaHQnKQogICAgIHJvdzIgPC0gaHVsbFBsb3QgKyBWU0RwbG90ICsKICAgICAgICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGd1aWRlcyA9ICdjb2xsZWN0JywKICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAyKSAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICdyaWdodCcpCiAgICAgCiAgICAgbWVhc3VyZXNQbG90IDwtIHJvdzEgLyByb3cyICsgcGF0Y2h3b3JrOjpwbG90X2xheW91dChoZWlnaHRzID0gYygxLzIsIDEvMiksIGJ5cm93ID0gRkFMU0UpCiAgICAgbWVhc3VyZXNQbG90CiAgICAgCiAgICAgcm0ocm93MSwgcm93MikKCiMjIFNhdmluZyB0aGUgcGxvdCAtLS0tCmdnc2F2ZShmaWxlbmFtZSA9ICJQbG90cy9NZWFzdXJlcy5wbmciLAogICAgICAgcGxvdCA9IG1lYXN1cmVzUGxvdCwKICAgICAgIGhlaWdodCA9IDUuNSwKICAgICAgIHdpZHRoID0gNiwKICAgICAgIHNjYWxlID0gLjgpCgojIFJlbW92aW5nIHVud2FudGVkIHZhcmlhYmxlcwogICAgIHJtKFZTQXBsb3QsCiAgICAgICAgVlNEcGxvdCwKICAgICAgICBodWxsUGxvdCwKICAgICAgICBDRHBsb3QsCiAgICAgICAgY29udmV4Q29vcmRzLAogICAgICAgIGZvcm1hbnRBbHBoYSwKICAgICAgICBmb3JtYW50Q29sb3IsCiAgICAgICAgZ2VvbS50ZXh0LnNpemUsCiAgICAgICAgbGluZUFscGhhLAogICAgICAgIGxpbmVDb2xvciwKICAgICAgICByLAogICAgICAgIHJmLAogICAgICAgIEhfaHBpLAogICAgICAgIGssCiAgICAgICAgbWF0Lm1lbHRlZCwKICAgICAgICBuY29udmV4XzI1LAogICAgICAgIG5jb252ZXhfNzUsCiAgICAgICAgblZTRF8yNSwKICAgICAgICBuVlNEXzc1LAogICAgICAgIGNvbnZleCwKICAgICAgICB2b3dlbERhdGEsCiAgICAgICAgRm9ybWFudHNfUFJBQVQsCiAgICAgICAgbWVhc3VyZXNQbG90LAogICAgICAgIHBsb3REYXRhKQogICAgIApgYGAKCiMjIEZpbHRlcmluZyBQcm9jZXNzCmBgYHtyfQpmb3JtYW50QWxwaGEgPC0gLjIwCm15UGFsIDwtIGMoIiMxMjc5QjUiLCIjMkQyRDM3IikKClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIi5QaXRjaCIsIGlnbm9yZS5jYXNlID0gVCkgJT4lCiAgICBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YS8iLC4sIHNlcCA9ICIiKSAlPiUKICAgIHJlYWQuZGVsaW0oLiwgaGVhZGVyID0gRikgJT4lCiAgICBkcGx5cjo6cmVuYW1lKFBpdGNoID0gVjEpICU+JQogICAgZHBseXI6Om11dGF0ZShQaXRjaCA9IGdzdWIoIi0tdW5kZWZpbmVkLS0iLE5BLFBpdGNoKSwKICAgICAgICAgICAgICAgICAgUGl0Y2ggPSBhcy5udW1lcmljKFBpdGNoKSkKCkZvcm1hbnRzX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhLyIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpCiAgCiAgYyA8LSAyCiAgd2hpbGUoYyA8IE5ST1coRm9ybWFudHNfUFJBQVQpKXsKICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10pCiAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdKQogICAgYyA8LSBjICsgMQogIH0KICBybShjKQogIAogICMgUmF3IEZvcm1hbnRzIC0tLS0KICBmMSA8LSBnZ3Bsb3QoYWVzKHg9RjJfYiwKICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgIGRhdGEgPSBGb3JtYW50c19QUkFBVCkgKyAKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBjb2xvciA9IG15UGFsWzJdKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDE2LDApKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZShsaW1pdHMgPSBjKDE5LDMpKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIlJhdyBGb3JtYW50XG5WYWx1ZXMiKSkgKyB4bGFiKCJGMiAoQmFyaykiKSArIHlsYWIoIkYxIChCYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgICAKIyBTdGVwICMxOiBWb2ljZWQgU2VnbWVudHMgLS0tLQogICAgcGxvdERhdGEgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgICAgICAgICAgICBkcGx5cjo6bXV0YXRlKGlzT3V0bGllciA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgICAgaXMubmEoUGl0Y2gpIH4gIlJlbW92ZWQiLAogICAgICAgICAgICAgICAgICAgICBUUlVFIH4gIlJldGFpbmVkIgogICAgICAgICAgICAgICAgICAgKSkKICAgIGYyIDwtIGdncGxvdChkYXRhID0gcGxvdERhdGEsCiAgICAgICAgICAgICAgICAgYWVzKHggPSBGMl9iLAogICAgICAgICAgICAgICAgICAgICB5ID0gRjFfYiwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBpc091dGxpZXIpKSArIAogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZW1vdmVkIikpICsKICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxLCBkYXRhID0gcGxvdERhdGEgJT4lCiAgICAgICAgICAgICBkcGx5cjo6ZmlsdGVyKGlzT3V0bGllciA9PSAiUmV0YWluZWQiKSkgKwogICAgICBzY2FsZV95X3JldmVyc2UobGltaXRzID0gYygxNiwwKSkgKwogICAgICBzY2FsZV94X3JldmVyc2UobGltaXRzID0gYygxOSwzKSkgKwogICAgICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJWb2ljZWQgU2VnbWVudHMiKSkgKwogICAgICB4bGFiKCJGMiAoQmFyaykiKSArCiAgICAgIHlsYWIoIkYxIChCYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsCiAgICAgICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT0xMikpCiAgICAKIyBTdGVwIDI6IE1BRCAtLS0tCiAgICBwbG90RGF0YSA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgICAgZHBseXI6Om11dGF0ZShGMV9tYWQgPSAoYWJzKEYxX0h6IC0gbWVkaWFuKEYxX0h6KSkvIG1hZChGMV9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBGMl9tYWQgPSAoYWJzKEYyX0h6IC0gbWVkaWFuKEYyX0h6KSkvIG1hZChGMl9IeiwgY29uc3RhbnQgPSAxLjQ4MjYpKSA+IDIuNSwKICAgICAgICAgICAgICAgICAgICBpc091dGxpZXIgPSBjYXNlX3doZW4oCiAgICAgICAgICAgICAgICAgICAgICBGMV9tYWQgPT0gVFJVRSB8IEYyX21hZCA9PSBUUlVFIH4gIlJlbW92ZWQiLAogICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICJSZXRhaW5lZCIKICAgICAgICAgICAgICAgKSkKICAgIAogICAgZjMgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlzT3V0bGllcikpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJlbW92ZWQiKSkgKwogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZXRhaW5lZCIpKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDE2LDApKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZShsaW1pdHMgPSBjKDE5LDMpKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKwogICAgICBsYWJzKHRpdGxlID0gcGFzdGUoIk1lZGlhbiBBYnNvbHV0ZVxuRGV2aWF0aW9uIikpICsKICAgICAgeGxhYigiRjIgKEJhcmspIikgKwogICAgICB5bGFiKCJGMSAoQmFyaykiKSArCiAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICBhc3BlY3QucmF0aW8gPSAxLAogICAgICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9MTIpKQogICAgCiMgU3RlcCAzOiBNYWhhbGFuaG9iaXMgRGlzdGFuY2UgLS0tLQogIHBsb3REYXRhIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICBkcGx5cjo6ZmlsdGVyKCFpcy5uYShQaXRjaCkpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKEYxX21hZCA9IChhYnMoRjFfSHogLSBtZWRpYW4oRjFfSHopKS8gbWFkKEYxX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41LAogICAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgICAgZHBseXI6OmZpbHRlcihGMV9tYWQgPT0gRkFMU0UgJiBGMl9tYWQgPT0gRkFMU0UpICU+JQogICAgICBkcGx5cjo6bXV0YXRlKG1EaXN0ID0gbWFoYWxhbm9iaXMoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sTWVhbnMoY2JpbmQoLiRGMV9IeiwgLiRGMl9IeikpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdiA9IGNvdihjYmluZCguJEYxX0h6LCAuJEYyX0h6KSkpLAogICAgICAgICAgICAgICAgICBtRGlzdF9zZCA9IGFicyhzY2FsZShtRGlzdCxjZW50ZXIgPSBUKSksCiAgICAgICAgICAgICAgICAgIGlzT3V0bGllciA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgICBtRGlzdF9zZCA8IDIgfiAiUmV0YWluZWQiLAogICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiUmVtb3ZlZCIKICAgICAgICAgICAgICAgICAgKSkKICAgIAogICAgZjQgPC0gZ2dwbG90KGRhdGEgPSBwbG90RGF0YSwKICAgICAgICAgICAgICAgICBhZXMoeCA9IEYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHkgPSBGMV9iLAogICAgICAgICAgICAgICAgICAgICBjb2xvciA9IGlzT3V0bGllcikpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgZGF0YSA9IHBsb3REYXRhICU+JQogICAgICAgICAgICAgICAgICAgZHBseXI6OmZpbHRlcihpc091dGxpZXIgPT0gIlJlbW92ZWQiKSkgKwogICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEsIGRhdGEgPSBwbG90RGF0YSAlPiUKICAgICAgICAgICAgIGRwbHlyOjpmaWx0ZXIoaXNPdXRsaWVyID09ICJSZXRhaW5lZCIpKSArCiAgICAgIHNjYWxlX3lfcmV2ZXJzZShsaW1pdHMgPSBjKDE2LDApKSArCiAgICAgIHNjYWxlX3hfcmV2ZXJzZShsaW1pdHMgPSBjKDE5LDMpKSArCiAgICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIk1haGFsYW5vYmlzXG5EaXN0YW5jZSIpKSArIHhsYWIoIkYyIChCYXJrKSIpICsgeWxhYigiRjEgKEJhcmspIikgKwogICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSwKICAgICAgICAgICAgYXNwZWN0LnJhdGlvID0gMSwKICAgICAgICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAgIAojIEZpbmFsIEZvcm1hbnRzIC0tLS0KICAgIHBsb3REYXRhIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikKICAgIAogICAgZjUgPC0gZ2dwbG90KGFlcyh4PUYyX2IsCiAgICAgICAgICAgICAgICAgICAgIHk9RjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IHBsb3REYXRhLAogICAgICAgICAgICAgICAgICAgICAgIGluaGVyaXQuYWVzID0gRkFMU0UpICsgCiAgICAgIGdlb21fcG9pbnQoc2hhcGUgPSAyMSwgY29sb3IgPSBteVBhbFsyXSkgKyAKICAgICAgc2NhbGVfeV9yZXZlcnNlKGxpbWl0cyA9IGMoMTYsMCkpICsKICAgICAgc2NhbGVfeF9yZXZlcnNlKGxpbWl0cyA9IGMoMTksMykpICsKICAgICAgdGhlbWVfY2xhc3NpYygpICsgbGFicyh0aXRsZSA9IHBhc3RlKCJGaW5hbCBGb3JtYW50XG5UcmFqZWN0b3JpZXMiKSkgKyB4bGFiKCJGMiAoQmFyaykiKSArIHlsYWIoIkYxIChCYXJrKSIpICsKICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEsIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKICAgIAojIENvbWliaW5nIHBsb3RzCiAgICBmaWx0ZXJlZFBsb3QgPC0gZjEgKyBmMiArIGYzICsgZjQgKyBmNSArIHBhdGNod29yazo6Z3VpZGVfYXJlYSgpICsKICAgICAgcGF0Y2h3b3JrOjpwbG90X2xheW91dChndWlkZXMgPSAnY29sbGVjdCcsCiAgICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gMykgKwogICAgICBwYXRjaHdvcms6OnBsb3RfYW5ub3RhdGlvbih0YWdfbGV2ZWxzID0gJ0EnKQogICAgZmlsdGVyZWRQbG90CiAgICAKICAgIGdnc2F2ZShwbG90ID0gZmlsdGVyZWRQbG90LCAiUGxvdHMvRmlsdGVyZWQgRm9ybWFudHMucG5nIiwKICAgICAgICAgICBoZWlnaHQgPSA2LAogICAgICAgICAgIHdpZHRoID0gOCwKICAgICAgICAgICB1bml0cyA9ICJpbiIsCiAgICAgICAgICAgc2NhbGUgPSAuODUpCiAgICAKICAgIHJtKGZpbHRlcmVkUGxvdCwKICAgICAgIFBpdGNoX1BSQUFULAogICAgICAgRm9ybWFudHNfUFJBQVQsCiAgICAgICBmMSwKICAgICAgIGYyLAogICAgICAgZjMsCiAgICAgICBmNCwKICAgICAgIGY1LAogICAgICAgZm9ybWFudEFscGhhLAogICAgICAgbXlQYWwsCiAgICAgICBwbG90RGF0YSkKICAKYGBgCgojIyBPVCB2cy4gVkFTCmBgYHtyfQpwbG90RGF0YV9JbnQgPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJfcmVsIiwgU3BlYWtlcikpICU+JQogIGRwbHlyOjpncm91cF9ieShTcGVha2VyKSAlPiUKICBkcGx5cjo6bXV0YXRlKHNlZ01pbiA9IGJhc2U6Om1pbihWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHNlZ01heCA9IGJhc2U6Om1heChWQVMsIHRyYW5zQWNjKSwKICAgICAgICAgICAgICAgIHJhdGluZ0F2ZyA9IG1lYW4oVkFTLCB0cmFuc0FjYywgbmEucm0gPSBUKSwKICAgICAgICAgICAgICAgIFNwZWFrZXIgPSBhcy5mYWN0b3IoU3BlYWtlciksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGNhc2Vfd2hlbigKICAgICAgICAgICAgICAgICAgRXRpb2xvZ3kgPT0gIkF0YXhpYyIgfiAiQXRheGlhIiwKICAgICAgICAgICAgICAgICAgVFJVRSB+IGFzLmNoYXJhY3RlcihFdGlvbG9neSkKICAgICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgICBFdGlvbG9neSA9IGFzLmZhY3RvcihFdGlvbG9neSkpICU+JQogIGFycmFuZ2Uoc2VnTWF4KQoKbXlfcGFsIDwtIGMoIiNmMjY0MzAiLCAiIzI3MkQyRCIsIiMyNTZlZmYiKQojIFdpdGggYSBiaXQgbW9yZSBzdHlsZQpwbG90X0ludCA8LSBnZ3Bsb3QocGxvdERhdGFfSW50KSArCiAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gZmN0X2lub3JkZXIoU3BlYWtlciksCiAgICAgICAgICAgICAgICAgICB4ZW5kID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICAgIHkgPSBzZWdNaW4sCiAgICAgICAgICAgICAgICAgICB5ZW5kID0gc2VnTWF4LAogICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSkpICsKICBnZW9tX3BvaW50KGFlcyh4ID0gU3BlYWtlciwKICAgICAgICAgICAgICAgICB5ID0gVkFTLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzFdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE5KSArCiAgZ2VvbV9wb2ludChhZXMoeCA9IFNwZWFrZXIsCiAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgIGNvbG9yID0gRXRpb2xvZ3kpLAogICAgICAgICAgICAgI2NvbG9yID0gbXlfcGFsWzJdLAogICAgICAgICAgICAgc2l6ZSA9IDMsCiAgICAgICAgICAgICBzaGFwZSA9IDE1KSArCiAgY29vcmRfZmxpcCgpKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUoCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsCiAgICBwYW5lbC5ib3JkZXIgPSBlbGVtZW50X2JsYW5rKCksCiAgKSArCiAgeGxhYigiIikgKwogIHlsYWIoIlNwZWVjaCBJbnRlbGxpZ2liaWxpdHkiKSArCiAgZ2d0aXRsZSgiU3BlZWNoIEludGVsbGlnaWJpbGl0eSIpICsKICB5bGltKGMoMCwxMDApKQoKCm15UGFsIDwtIGMoIiMxQUFENzciLCAiIzEyNzlCNSIsICIjRkZCRjAwIiwgIiNGRDc4NTMiLCAiI0JGMzE3OCIpCm15U2hhcGVzIDwtIGMoMTYsIDE4LCAxNywgMTUpCgpPVF9WQVNzY2F0dGVyIDwtIGdncGxvdChwbG90RGF0YV9JbnQsCiAgICAgICAgICAgICAgICAgIGFlcyh4ID0gVkFTLAogICAgICAgICAgICAgICAgICAgICAgeSA9IHRyYW5zQWNjLAogICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSBFdGlvbG9neSwKICAgICAgICAgICAgICAgICAgICAgIHNoYXBlID0gRXRpb2xvZ3ksCiAgICAgICAgICAgICAgICAgICAgICBsaW5ldHlwZSA9IEV0aW9sb2d5KSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSArCiAgZ2VvbV9hYmxpbmUoaW50ZXJjZXB0ID0gMCwgc2xvcGUgPSAxKSArCiAgY29vcmRfY2FydGVzaWFuKHhsaW0gPSBjKDAsMTAwKSwgeWxpbSA9IGMoMCwxMDApKSArCiAgbGFicyh4ID0gIkludGVsbGlnaWJpbGl0eSAoVkFTKSIsIHkgPSAiSW50ZWxsaWdpYmlsaXR5IChPVCkiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15U2hhcGVzKSArCiAgdGhlbWVfY2xhc3NpYygpICsKICB0aGVtZShhc3BlY3QucmF0aW89MSwKICAgICAgICBsZWdlbmQucG9zaXRpb249InJpZ2h0IikKCgpnZ3NhdmUoZmlsZW5hbWUgPSAiUGxvdHMvT1QgYW5kIFZBUyBTY2F0dGVycGxvdC5wbmciLAogICAgICAgcGxvdCA9IE9UX1ZBU3NjYXR0ZXIsCiAgICAgICBoZWlnaHQgPSAzLjI1LAogICAgICAgd2lkdGggPSA0LAogICAgICAgdW5pdHMgPSAiaW4iLAogICAgICAgc2NhbGUgPSAxKQoKcm0oc2NhdHRlcjEsIHNjYXR0ZXIyLCBjb21iaW5lZFNjYXR0ZXIpCmBgYAoKIyMgTW9kZWwgU2NhdHRlcnBsb3RzCmBgYHtyfQptb2RlbEZpZ3VyZURhdGEgPC0gQWNvdXN0aWNEYXRhICU+JQogIGRwbHlyOjpmaWx0ZXIoIWdyZXBsKCJfcmVsIixTcGVha2VyKSkgJT4lCiAgZHBseXI6OnNlbGVjdChTcGVha2VyLCBFdGlvbG9neSwgU2V4LCBWU0FfYiwgdm93ZWxfRURfYiwgSHVsbF9iLCBIdWxsX2JWU0RfMjUsIEh1bGxfYlZTRF83NSwgVkFTLCB0cmFuc0FjYykgJT4lCiAgZHBseXI6Om11dGF0ZShTcGVha2VyID0gYXMuZmFjdG9yKFNwZWFrZXIpLAogICAgICAgICAgICAgICAgRXRpb2xvZ3kgPSBhcy5mYWN0b3IoRXRpb2xvZ3kpLAogICAgICAgICAgICAgICAgU2V4ID0gYXMuZmFjdG9yKFNleCkpICU+JQogIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scyA9IFZBUzp0cmFuc0FjYywgbmFtZXNfdG8gPSAiSW50VHlwZSIsIHZhbHVlc190byA9ICJJbnQiKSAlPiUKICBkcGx5cjo6bXV0YXRlKEludFR5cGUgPSBjYXNlX3doZW4oCiAgICBJbnRUeXBlID09ICJ0cmFuc0FjYyIgfiAiT1QiLAogICAgVFJVRSB+ICJWQVMiCiAgKSwKICAgICAgICAgICAgICAgIEludFR5cGUgPSBhcy5mYWN0b3IoSW50VHlwZSkpCgp5bGFiZWwgPC0gIkludGVsbGlnaWJpbGl0eSIKbXlQYWwgPC0gYygiIzJEMkQzNyIsICIjMTI3OUI1IikKbXlQYWxTaGFwZSA8LSBjKDE5LCAxKQoKVlNBIDwtIG1vZGVsRmlndXJlRGF0YSAlPiUKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSBWU0FfYiwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0EgKEJhcmsiXjIqIikiKSkgKwogIHlsYWIoeWxhYmVsKSArCiAgY29vcmRfY2FydGVzaWFuKHlsaW0gPSBjKDAsMTAwKSkgKwogIHRoZW1lX2NsYXNzaWMoKSArCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXNwZWN0LnJhdGlvPTEpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gbXlQYWwpICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzID0gbXlQYWxTaGFwZSkgKwogIGxhYnMoY29sb3I9IkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIHNoYXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIiwKICAgICAgIGxpbmV0eXBlID0gIkludGVsbGlnaWJpbGl0eSBUeXBlIikKCmRpc3AgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IHZvd2VsX0VEX2IsCiAgICAgIHkgPSBJbnQsCiAgICAgIGNvbG9yID0gSW50VHlwZSwKICAgICAgc2hhcGUgPSBJbnRUeXBlLAogICAgICBsaW5ldHlwZSA9IEludFR5cGUpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwgZmlsbCA9ICJsaWdodCBncmV5IikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKwogIHhsYWIoIkNvcm5lciBEaXNwZXJzaW9uIChCYXJrKSIpICsKICB5bGFiKHlsYWJlbCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDEwMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IG15UGFsKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcyA9IG15UGFsU2hhcGUpICsKICBsYWJzKGNvbG9yPSJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBzaGFwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIsCiAgICAgICBsaW5ldHlwZSA9ICJJbnRlbGxpZ2liaWxpdHkgVHlwZSIpCgpIdWxsIDwtIG1vZGVsRmlndXJlRGF0YSAlPiUKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSBIdWxsX2IsCiAgICAgIHkgPSBJbnQsCiAgICAgIGNvbG9yID0gSW50VHlwZSwKICAgICAgc2hhcGUgPSBJbnRUeXBlLAogICAgICBsaW5ldHlwZSA9IEludFR5cGUpICsKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gVCwgZmlsbCA9ICJsaWdodCBncmV5IikgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRikgKwogIHhsYWIoZXhwcmVzc2lvbigiVlNBIltIdWxsXSoiIChCYXJrIl4yKiIpIikpICsKICB5bGFiKHlsYWJlbCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDEwMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKdnNkMjUgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IEh1bGxfYlZTRF8yNSwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0QiWzI1XSoiIChCYXJrIl4yKiIpIikpICsKICB5bGFiKHlsYWJlbCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDEwMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKdnNkNzUgPC0gbW9kZWxGaWd1cmVEYXRhICU+JQogIGdncGxvdCgpICsKICBhZXMoeCA9IEh1bGxfYlZTRF83NSwKICAgICAgeSA9IEludCwKICAgICAgY29sb3IgPSBJbnRUeXBlLAogICAgICBzaGFwZSA9IEludFR5cGUsCiAgICAgIGxpbmV0eXBlID0gSW50VHlwZSkgKwogIGdlb21fcG9pbnQoKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBULCBmaWxsID0gImxpZ2h0IGdyZXkiKSArCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGKSArCiAgeGxhYihleHByZXNzaW9uKCJWU0QiWzc1XSoiIChCYXJrIl4yKiIpIikpICsKICB5bGFiKHlsYWJlbCkgKwogIGNvb3JkX2NhcnRlc2lhbih5bGltID0gYygwLDEwMCkpICsKICB0aGVtZV9jbGFzc2ljKCkgKwogIHRoZW1lKGFzcGVjdC5yYXRpbz0xKSArIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikgKwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBteVBhbCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXMgPSBteVBhbFNoYXBlKSArCiAgbGFicyhjb2xvcj0iSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgc2hhcGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiLAogICAgICAgbGluZXR5cGUgPSAiSW50ZWxsaWdpYmlsaXR5IFR5cGUiKQoKIyBDcmVhdGluZyBPVCBTY2F0dGVycGxvdCBGaWd1cmUKCnNjYXR0ZXIgPC0gVlNBICArIGRpc3AgKyBwYXRjaHdvcms6Omd1aWRlX2FyZWEoKSArIEh1bGwgKyB2c2QyNSArIHZzZDc1ICsKICBwYXRjaHdvcms6OnBsb3RfbGF5b3V0KGd1aWRlcyA9ICdjb2xsZWN0JywKICAgICAgICAgICAgICAgICAgICAgICAgIG5jb2wgPSAzKSAmIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCnNjYXR0ZXIgCgpnZ3NhdmUoIlBsb3RzL01vZGVsRmlndXJlLnBuZyIsIHNjYXR0ZXIsCiAgICAgICBoZWlnaHQgPSA0LAogICAgICAgd2lkdGggPSA2LAogICAgICAgdW5pdHMgPSAiaW4iLAogICAgICAgc2NhbGUgPSAxLjEpCmBgYAoKIyMgRmlsdGVyaW5nIGF0IERpZmZlcmVudCBMZXZlbHMKYGBge3J9CnRleHRfeCA8LSAxMi41CnRleHRfeSA8LSA4LjUKeGxpbXMgPC0gYygxNiw1KQp5bGltcyA8LSBjKDksMSkKIyBIdWxsIC0gMiBTRCAtLS0tClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICAjZHBseXI6Om11dGF0ZShtRGlzdE91dGxpZXIgPSAoc3RhdHM6OnBjaGlzcShtRGlzdCwgZGY9MSwgbG93ZXIudGFpbD1GQUxTRSkpIDwgLjAwMSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMikKICAKICBjIDwtIDIKICB3aGlsZShjIDwgTlJPVyhGb3JtYW50c19QUkFBVCkpewogICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSkKICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10pCiAgICBjIDwtIGMgKyAxCiAgfQogIHJtKGMpCiAgCiAgICBIdWxsX2IgPC0gY0h1bGwoRm9ybWFudHNfUFJBQVQkRjFfYiwgRm9ybWFudHNfUFJBQVQkRjJfYikKIyMjIFBsb3R0aW5nIEh1bGwKICAgICAgY29udmV4Q29vcmRzIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoRjFfYiwgRjJfYikgJT4lCiAgICAgICAgYXMubWF0cml4KCkgJT4lCiAgICAgICAgZ3JEZXZpY2VzOjpjaHVsbCgpCiAgICAgIGNvbnZleCA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICBzbGljZShjb252ZXhDb29yZHMpCgogICAgICBodWxsUGxvdF8yIDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHRleHRfeCwgeSA9IHRleHRfeSwgbGFiZWwgPSBwYXN0ZSgiSHVsbCA9Iixyb3VuZChIdWxsX2IsMikpKSArCiAgICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgICB4bGltKHhsaW1zKSArCiAgICAgICAgeWxpbSh5bGltcykgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiMiBTRCIpKSArIHhsYWIoIkYyIChCYXJrKSIpICsgeWxhYigiRjEgKEJhcmspIikgKwogICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICAgIGh1bGxQbG90XzIKICAgICAgCiMgSHVsbCAtIDIuNSBTRCAtLS0tClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICAjZHBseXI6Om11dGF0ZShtRGlzdE91dGxpZXIgPSAoc3RhdHM6OnBjaGlzcShtRGlzdCwgZGY9MSwgbG93ZXIudGFpbD1GQUxTRSkpIDwgLjAwMSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMi41KQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAgIEh1bGxfYiA8LSBjSHVsbChGb3JtYW50c19QUkFBVCRGMV9iLCBGb3JtYW50c19QUkFBVCRGMl9iKQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90XzIuNSA8LSBnZ3Bsb3QoYWVzKEYyX2IsIEYxX2IpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArCiAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSArCiAgICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBjb252ZXgsCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjUsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB0ZXh0X3gsIHkgPSB0ZXh0X3ksIGxhYmVsID0gcGFzdGUoIkh1bGwgPSIscm91bmQoSHVsbF9iLDIpKSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgeGxpbSh4bGltcykgKwogICAgICAgIHlsaW0oeWxpbXMpICsKICAgICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIjIuNSBTRCIpKSArIHhsYWIoIkYyIChCYXJrKSIpICsgeWxhYigiRjEgKEJhcmspIikgKwogICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICAgIGh1bGxQbG90XzIuNQogICAgICAKIyBIdWxsIC0gMyBTRCAtLS0tClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICAjZHBseXI6Om11dGF0ZShtRGlzdE91dGxpZXIgPSAoc3RhdHM6OnBjaGlzcShtRGlzdCwgZGY9MSwgbG93ZXIudGFpbD1GQUxTRSkpIDwgLjAwMSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMykKICAKICBjIDwtIDIKICB3aGlsZShjIDwgTlJPVyhGb3JtYW50c19QUkFBVCkpewogICAgRm9ybWFudHNfUFJBQVQkRjFfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMV9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSkKICAgIEZvcm1hbnRzX1BSQUFUJEYyX0h6W2NdIDwtIGlmZWxzZShpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjLTFdKSAmJgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaXMubmEoRm9ybWFudHNfUFJBQVQkRjJfSHpbYysxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTkEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10pCiAgICBjIDwtIGMgKyAxCiAgfQogIHJtKGMpCiAgCiAgICBIdWxsX2IgPC0gY0h1bGwoRm9ybWFudHNfUFJBQVQkRjFfYiwgRm9ybWFudHNfUFJBQVQkRjJfYikKIyMjIFBsb3R0aW5nIEh1bGwKICAgICAgY29udmV4Q29vcmRzIDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIGRwbHlyOjpzZWxlY3QoRjFfYiwgRjJfYikgJT4lCiAgICAgICAgYXMubWF0cml4KCkgJT4lCiAgICAgICAgZ3JEZXZpY2VzOjpjaHVsbCgpCiAgICAgIGNvbnZleCA8LSBGb3JtYW50c19QUkFBVCAlPiUKICAgICAgICBzbGljZShjb252ZXhDb29yZHMpCgogICAgICBodWxsUGxvdF8zIDwtIGdncGxvdChhZXMoRjJfYiwgRjFfYiksCiAgICAgICAgICAgICAgICAgICAgICAgICBkYXRhID0gRm9ybWFudHNfUFJBQVQpICsKICAgICAgICBnZW9tX3BvaW50KHNoYXBlID0gMjEpICsKICAgICAgICBnZW9tX3BvbHlnb24oZGF0YSA9IGNvbnZleCwKICAgICAgICAgICAgICAgICAgICAgYWxwaGEgPSAuNSwKICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiIzEyNzlCNSIsCiAgICAgICAgICAgICAgICAgICAgIGZpbGwgPSBOQSwKICAgICAgICAgICAgICAgICAgICAgc2l6ZSA9IDEuNSkgKwogICAgICAgIGFubm90YXRlKCJ0ZXh0IiwgeCA9IHRleHRfeCwgeSA9IHRleHRfeSwgbGFiZWwgPSBwYXN0ZSgiSHVsbCA9Iixyb3VuZChIdWxsX2IsMikpKSArCiAgICAgICAgc2NhbGVfeV9yZXZlcnNlKCkgKwogICAgICAgIHNjYWxlX3hfcmV2ZXJzZSgpICsKICAgICAgICB4bGltKHhsaW1zKSArCiAgICAgICAgeWxpbSh5bGltcykgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIGxhYnModGl0bGUgPSBwYXN0ZSgiMyBTRCIpKSArIHhsYWIoIkYyIChCYXJrKSIpICsgeWxhYigiRjEgKEJhcmspIikgKwogICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICAgIGh1bGxQbG90XzMKICAgICAgCiMgSHVsbCAtIDEuNSBTRCAtLS0tClBpdGNoX1BSQUFUIDwtIGxpc3QuZmlsZXMocGF0aCA9IHBhc3RlKCJQcmVwcGVkIERhdGEvRXhhbXBsZSBEYXRhIiwgc2VwID0gIiIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICIuUGl0Y2giLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IEYpICU+JQogICAgZHBseXI6OnJlbmFtZShQaXRjaCA9IFYxKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoUGl0Y2ggPSBnc3ViKCItLXVuZGVmaW5lZC0tIixOQSxQaXRjaCksCiAgICAgICAgICAgICAgICAgIFBpdGNoID0gYXMubnVtZXJpYyhQaXRjaCkpCgpGb3JtYW50c19QUkFBVCA8LSBsaXN0LmZpbGVzKHBhdGggPSBwYXN0ZSgiUHJlcHBlZCBEYXRhL0V4YW1wbGUgRGF0YSIsIHNlcCA9ICIiKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiX0Zvcm1hbnQiLCBpZ25vcmUuY2FzZSA9IFQpICU+JQogICAgcGFzdGUoIlByZXBwZWQgRGF0YS9FeGFtcGxlIERhdGEvIiwuLCBzZXAgPSAiIikgJT4lCiAgICByZWFkLmRlbGltKC4sIGhlYWRlciA9IFQpICU+JQogICAgZHBseXI6OnNlbGVjdCghYyhuZm9ybWFudHMsIEIxLkh6LiwgQjIuSHouLCBCMy5Iei4sIEY0Lkh6LiwgQjQuSHouLCBGNS5Iei4sIEI1Lkh6LikpICU+JQogICAgZHBseXI6OnJlbmFtZShUaW1lX3MgPSB0aW1lLnMuLAogICAgICAgICAgICAgICAgICBGMV9IeiA9IEYxLkh6LiwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBGMi5Iei4sCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gRjMuSHouKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfSHogPSBpZmVsc2UoRjFfSHogPT0gMCwgTkEsIEYxX0h6KSwKICAgICAgICAgICAgICAgICAgRjJfSHogPSBpZmVsc2UoRjJfSHogPT0gMCwgTkEsIEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfSHogPSBpZmVsc2UoRjNfSHogPT0gMCwgTkEsIEYzX0h6KSkgJT4lCiAgICBkcGx5cjo6bXV0YXRlKEYxX0h6ID0gYXMubnVtZXJpYyhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX0h6ID0gYXMubnVtZXJpYyhGMl9IeiksCiAgICAgICAgICAgICAgICAgIEYzX0h6ID0gc3VwcHJlc3NXYXJuaW5ncyhhcy5udW1lcmljKEYzX0h6KSksCiAgICAgICAgICAgICAgICAgIFRpbWVfbXMgPSBUaW1lX3MgLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9rSHogPSBGMV9IeiAvIDEwMDAsCiAgICAgICAgICAgICAgICAgIEYyX2tIeiA9IEYyX0h6IC8gMTAwMCwKICAgICAgICAgICAgICAgICAgRjNfa0h6ID0gRjNfSHogLyAxMDAwLAogICAgICAgICAgICAgICAgICBGMV9iID0gZW11Ujo6YmFyayhGMV9IeiksCiAgICAgICAgICAgICAgICAgIEYyX2IgPSBlbXVSOjpiYXJrKEYyX0h6KSwKICAgICAgICAgICAgICAgICAgRjNfYiA9IGVtdVI6OmJhcmsoRjNfSHopKSAlPiUKICAgIGRwbHlyOjpzZWxlY3QoIVRpbWVfcykgJT4lCiAgICBkcGx5cjo6cmVsb2NhdGUoVGltZV9tcywgLmJlZm9yZSA9IEYxX0h6KSAlPiUKICAgIGNiaW5kKC4sUGl0Y2hfUFJBQVQpICU+JQogICAgZHBseXI6OmZpbHRlcighaXMubmEoUGl0Y2gpKSAlPiUKICAgIGRwbHlyOjptdXRhdGUoRjFfbWFkID0gKGFicyhGMV9IeiAtIG1lZGlhbihGMV9IeikpLyBtYWQoRjFfSHosIGNvbnN0YW50ID0gMS40ODI2KSkgPiAyLjUsCiAgICAgICAgICAgICAgICAgIEYyX21hZCA9IChhYnMoRjJfSHogLSBtZWRpYW4oRjJfSHopKS8gbWFkKEYyX0h6LCBjb25zdGFudCA9IDEuNDgyNikpID4gMi41KSAlPiUKICAgIGRwbHlyOjpmaWx0ZXIoRjFfbWFkID09IEZBTFNFICYgRjJfbWFkID09IEZBTFNFKSAlPiUKICAgIGRwbHlyOjptdXRhdGUobURpc3QgPSBtYWhhbGFub2JpcyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xNZWFucyhjYmluZCguJEYxX0h6LCAuJEYyX0h6KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY292ID0gY292KGNiaW5kKC4kRjFfSHosIC4kRjJfSHopKSksCiAgICAgICAgICAgICAgICAgIG1EaXN0X3NkID0gYWJzKHNjYWxlKG1EaXN0LGNlbnRlciA9IFQpKSkgJT4lCiAgICAjZHBseXI6Om11dGF0ZShtRGlzdE91dGxpZXIgPSAoc3RhdHM6OnBjaGlzcShtRGlzdCwgZGY9MSwgbG93ZXIudGFpbD1GQUxTRSkpIDwgLjAwMSkgJT4lCiAgICBkcGx5cjo6ZmlsdGVyKG1EaXN0X3NkIDwgMS41KQogIAogIGMgPC0gMgogIHdoaWxlKGMgPCBOUk9XKEZvcm1hbnRzX1BSQUFUKSl7CiAgICBGb3JtYW50c19QUkFBVCRGMV9IeltjXSA8LSBpZmVsc2UoaXMubmEoRm9ybWFudHNfUFJBQVQkRjFfSHpbYy0xXSkgJiYKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYxX0h6W2MrMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5BLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIEZvcm1hbnRzX1BSQUFUJEYxX0h6W2NdKQogICAgRm9ybWFudHNfUFJBQVQkRjJfSHpbY10gPC0gaWZlbHNlKGlzLm5hKEZvcm1hbnRzX1BSQUFUJEYyX0h6W2MtMV0pICYmCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpcy5uYShGb3JtYW50c19QUkFBVCRGMl9IeltjKzFdKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOQSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBGb3JtYW50c19QUkFBVCRGMl9IeltjXSkKICAgIGMgPC0gYyArIDEKICB9CiAgcm0oYykKICAKICAgIEh1bGxfYiA8LSBjSHVsbChGb3JtYW50c19QUkFBVCRGMV9iLCBGb3JtYW50c19QUkFBVCRGMl9iKQojIyMgUGxvdHRpbmcgSHVsbAogICAgICBjb252ZXhDb29yZHMgPC0gRm9ybWFudHNfUFJBQVQgJT4lCiAgICAgICAgZHBseXI6OnNlbGVjdChGMV9iLCBGMl9iKSAlPiUKICAgICAgICBhcy5tYXRyaXgoKSAlPiUKICAgICAgICBnckRldmljZXM6OmNodWxsKCkKICAgICAgY29udmV4IDwtIEZvcm1hbnRzX1BSQUFUICU+JQogICAgICAgIHNsaWNlKGNvbnZleENvb3JkcykKCiAgICAgIGh1bGxQbG90XzEuNSA8LSBnZ3Bsb3QoYWVzKEYyX2IsIEYxX2IpLAogICAgICAgICAgICAgICAgICAgICAgICAgZGF0YSA9IEZvcm1hbnRzX1BSQUFUKSArCiAgICAgICAgZ2VvbV9wb2ludChzaGFwZSA9IDIxKSArCiAgICAgICAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBjb252ZXgsCiAgICAgICAgICAgICAgICAgICAgIGFscGhhID0gLjUsCiAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIiMxMjc5QjUiLAogICAgICAgICAgICAgICAgICAgICBmaWxsID0gTkEsCiAgICAgICAgICAgICAgICAgICAgIHNpemUgPSAxLjUpICsKICAgICAgICBhbm5vdGF0ZSgidGV4dCIsIHggPSB0ZXh0X3gsIHkgPSB0ZXh0X3ksIGxhYmVsID0gcGFzdGUoIkh1bGwgPSIscm91bmQoSHVsbF9iLDIpKSkgKwogICAgICAgIHNjYWxlX3lfcmV2ZXJzZSgpICsKICAgICAgICBzY2FsZV94X3JldmVyc2UoKSArCiAgICAgICAgeGxpbSh4bGltcykgKwogICAgICAgIHlsaW0oeWxpbXMpICsKICAgICAgICB0aGVtZV9jbGFzc2ljKCkgKyBsYWJzKHRpdGxlID0gcGFzdGUoIjEuNSBTRCIpKSArIHhsYWIoIkYyIChCYXJrKSIpICsgeWxhYigiRjEgKEJhcmspIikgKwogICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgICAgIGFzcGVjdC5yYXRpbyA9IDEpCiAgICAgIGh1bGxQbG90XzEuNQogICAgICAKIyBDb21iaW5lZCAtLS0tCiAgICAgIGdncHVicjo6Z2dhcnJhbmdlKGh1bGxQbG90XzEuNSwgaHVsbFBsb3RfMiwgaHVsbFBsb3RfMi41LCBodWxsUGxvdF8zLAogICAgICAgICAgICAgICAgICAgICAgICBuY29sID0gNCkKICAgICAgZ2dzYXZlKGZpbGVuYW1lID0gIlBsb3RzL0h1bGwgYXQgRGlmZmVyZW50IEZpbHRlcnMucG5nIiwKICAgICAgICAgICAgIGhlaWdodCA9IDMsCiAgICAgICAgICAgICB3aWR0aD0gOSwKICAgICAgICAgICAgIHVuaXRzID0gImluIiwKICAgICAgICAgICAgIHNjYWxlID0gLjkpCiAgICAgIApgYGAKIyBEZW1vZ3JhcGhpYyBJbmZvCiMjIExpc3RlbmVycwpgYGB7cn0KCkxpc3RlbmVycyAlPiUKICBmdXJuaXR1cmU6OnRhYmxlMShhZ2UsIGdlbmRlciwgcmFjZSwgZXRobmljaXR5KQoKcm0oTGlzdGVuZXJzKQoKYGBgCgojIyBTcGVha2VycwpgYGB7cn0KCkFnZXMgPC0gcmlvOjppbXBvcnQoIlByZXBwZWQgRGF0YS9TcGVha2VyIEFnZXMueGxzeCIpCgpTcGVha2VyRGVtbyA8LSBBY291c3RpY0RhdGEgJT4lCiAgZHBseXI6OnNlbGVjdChjKFNwZWFrZXIsIFNleCwgRXRpb2xvZ3kpKSAlPiUKICBmdWxsX2pvaW4oLiwgQWdlcywgYnkgPSAiU3BlYWtlciIpCgpTcGVha2VyRGVtbyAlPiUKICBmdXJuaXR1cmU6OnRhYmxlMShTZXgsIEV0aW9sb2d5LCBBZ2UsIG5hLnJtID0gRikKClNwZWFrZXJEZW1vICU+JQogIGRwbHlyOjpzdW1tYXJpemUobWVhbl9hZ2UgPSBtZWFuKEFnZSwgbmEucm0gPSBUKSwgYWdlX3NkID0gc2QoQWdlLCBuYS5ybSA9IFQpLCBhZ2VfcmFuZ2UgPSByYW5nZShBZ2UsIG5hLnJtID0gVCkpCgojIFJlbW92aW5nIHVud2FudGVkIHZhcmlhYmxlcwpybShBZ2VzLCBTcGVha2VyRGVtbykKCmBgYAoK